mirror of
https://github.com/0x5eal/luau-unzip.git
synced 2025-04-10 17:20:53 +01:00
fix: improve validation and and fix regression in tests
Previous EoCD detection performance improvement changes in https://github.com/0x5eal/luau-unzip/commit/b710e296 inadvertently fixed some bugs to do with max size ZIP reads, which caused a regression in the `invalid_cde_number_of_files_allocation_greater_offset.zip` test, which used to error as expected due to out-of-bounds buffer reads. This commit fixes this by improving size validations present in the methods `ZipReader:parseEocdRecord` and `ZipReader:parseCentralDirectory`.
This commit is contained in:
parent
545de01536
commit
39009b734c
1 changed files with 14 additions and 2 deletions
|
@ -531,12 +531,18 @@ function ZipReader.parseEocdRecord(self: ZipReader, pos: number): EocdRecord
|
||||||
local cdSize = buffer.readu32(self.data, pos + 12)
|
local cdSize = buffer.readu32(self.data, pos + 12)
|
||||||
local cdOffset = buffer.readu32(self.data, pos + 16)
|
local cdOffset = buffer.readu32(self.data, pos + 16)
|
||||||
|
|
||||||
-- Validate CD boundaries and entry count
|
-- Validate CD boundaries and entry count; Ensure minimum size is at least 30 bytes and
|
||||||
|
-- total size after the local header is not larger than the buffer size
|
||||||
local bufSize = buffer.len(self.data)
|
local bufSize = buffer.len(self.data)
|
||||||
if cdOffset >= bufSize or cdOffset + cdSize > bufSize then
|
if cdOffset >= bufSize or cdOffset < 30 or cdOffset + cdSize > bufSize then
|
||||||
error("Invalid Central Directory offset or size")
|
error("Invalid Central Directory offset or size")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Validate CD size range; min = 46 bytes per entry, max = 0xFFFF * 3 + 46 bytes per entry
|
||||||
|
if cdSize < cdEntries * 46 or cdEntries * (0xFFFF * 3 + 46) < cdSize then
|
||||||
|
error("Invalid Central Directory size for claimed number of entries")
|
||||||
|
end
|
||||||
|
|
||||||
local commentLength = buffer.readu16(self.data, pos + 20)
|
local commentLength = buffer.readu16(self.data, pos + 20)
|
||||||
return {
|
return {
|
||||||
diskNumber = buffer.readu16(self.data, pos + 4),
|
diskNumber = buffer.readu16(self.data, pos + 4),
|
||||||
|
@ -609,6 +615,11 @@ function ZipReader.parseCentralDirectory(self: ZipReader): ()
|
||||||
local offset = buffer.readu32(self.data, pos + 42)
|
local offset = buffer.readu32(self.data, pos + 42)
|
||||||
local name = buffer.readstring(self.data, pos + 46, nameLength)
|
local name = buffer.readstring(self.data, pos + 46, nameLength)
|
||||||
|
|
||||||
|
local entrySize = 46 + nameLength + extraLength + commentLength
|
||||||
|
if pos + entrySize > record.cdOffset + record.cdSize then
|
||||||
|
error("Invalid Central Directory entry size")
|
||||||
|
end
|
||||||
|
|
||||||
table.insert(
|
table.insert(
|
||||||
self.entries,
|
self.entries,
|
||||||
ZipEntry.new(offset, name, {
|
ZipEntry.new(offset, name, {
|
||||||
|
@ -630,6 +641,7 @@ function ZipReader.parseCentralDirectory(self: ZipReader): ()
|
||||||
if entriesFound ~= record.cdEntries then
|
if entriesFound ~= record.cdEntries then
|
||||||
error("Found different entries than specified in Central Directory")
|
error("Found different entries than specified in Central Directory")
|
||||||
end
|
end
|
||||||
|
|
||||||
self.comment = record.comment
|
self.comment = record.comment
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue