Report malformed zip headers instead of raising

A central directory record or local header cut short of its length fields
made zip_entries and zip_data do arithmetic on nil, so the parse raised
where every other failure returns nil, err. Bound both against the buffer
first. A pax record claiming a zero length no longer spins forever.
This commit is contained in:
2026-09-10 23:18:22 +10:00
parent 04506285df
commit 407ad8093f
+12
View File
@@ -140,6 +140,11 @@ local function zip_entries(buf)
if u32(buf, pos) ~= CD_SIG then
return nil, 'malformed central directory'
end
-- The fixed 46-byte header has to be there in full, otherwise the fields
-- read below are nil and the parse blows up instead of reporting.
if pos + 45 > #buf then
return nil, 'truncated central directory'
end
local namelen = u16(buf, pos + 28)
local entry = {
version_made_by = u16(buf, pos + 4),
@@ -166,6 +171,9 @@ local function zip_data(buf, entry)
if u32(buf, lho) ~= LOCAL_SIG then
return reject(entry.name, 'invalid local header signature')
end
if lho + 29 > #buf then
return reject(entry.name, 'truncated local header')
end
local start = lho + 30 + u16(buf, lho + 26) + u16(buf, lho + 28)
local data
@@ -262,6 +270,10 @@ local function pax_records(block)
break
end
len = tonumber(len)
-- A zero length would leave pos where it is and spin forever.
if len < 1 then
break
end
local record = block:sub(rest, pos + len - 2)
local key, value = record:match('^([^=]+)=(.*)$')
if key then