diff --git a/tests/archive_spec.lua b/tests/archive_spec.lua index 88101d6..636d566 100644 --- a/tests/archive_spec.lua +++ b/tests/archive_spec.lua @@ -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)