Aim the truncated-directory test at the raising path
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful

A record whose name is cut short already reported; the raise needed a
zero-length name and a directory offset pointing into the trailing
comment. Build that case instead.
This commit is contained in:
2026-09-10 23:25:40 +10:00
parent 78a5df6cf3
commit 11c8fbf485
+10 -4
View File
@@ -322,8 +322,8 @@ t.describe('archive.extract zip', function()
end)
t.describe('archive.extract zip malformed directory', function()
-- A central directory record that stops before its extra-field and comment
-- lengths used to raise instead of reporting.
-- A central directory record that stops short of its own header used to
-- raise instead of reporting.
local function truncate_cd(keep)
local bytes = zipf({ { name = 'root/a.lua', data = 'hi' } })
local cd = bytes:find('PK\1\2', 1, true)
@@ -331,8 +331,14 @@ t.describe('archive.extract zip malformed directory', function()
return bytes:sub(1, cd + keep - 1) .. bytes:sub(eocd)
end
t.it('reports a record cut off before its length fields', function()
local ok, err = extract(truncate_cd(30))
t.it('reports a record cut off before its extra-field lengths', function()
-- The directory offset is attacker-controlled, so point it at a record
-- planted in the trailing comment: a zero name length lets the parse run
-- cleanly up to the extra-field and comment lengths, which is where it
-- used to raise.
local comment = 'PK\1\2' .. string.rep('\0', 26)
local bytes = zipf({ { name = 'root/a.lua', data = 'hi' }, comment = comment })
local ok, err = extract(patch32(bytes, #bytes - #comment - 21 + 16, #bytes - #comment))
t.falsy(ok)
t.matches('truncated central directory', err)
end)