fix: deflate decompression failing for files with high compression ratio

This commit is contained in:
Erica Marigold 2025-01-02 06:07:53 +00:00
parent 6f4083f10f
commit 06b1f1a640
Signed by: DevComp
GPG key ID: 429EF1C337871656
2 changed files with 305 additions and 300 deletions

View file

@ -343,11 +343,13 @@ local function inflateUncompressedBlock(d: Data)
end end
--- Main decompression function that processes DEFLATE compressed data --- Main decompression function that processes DEFLATE compressed data
local function uncompress(source: buffer): buffer local function uncompress(source: buffer, uncompressedSize: number?): buffer
-- FIXME: This is a temporary solution to avoid a buffer overflow local dest = buffer.create(
-- We likely want some type of reflection with the zip metadata to -- If the uncompressed size is known, we use that, otherwise we use a default
-- have a definitive buffer size -- size that is a 7 times more than the compressed size; this factor works
local dest = buffer.create(buffer.len(source) * 7) -- well for most cases other than those with a very high compression ratio
uncompressedSize or buffer.len(source) * 7
)
local d = Data.new(source, dest) local d = Data.new(source, dest)
repeat repeat

View file

@ -32,16 +32,19 @@ local function validateCrc(decompressed: buffer, validation: CrcValidationOption
end end
end end
local DECOMPRESSION_ROUTINES: { [number]: (buffer, validation: CrcValidationOptions) -> buffer } = table.freeze({ local DECOMPRESSION_ROUTINES: { [number]: (buffer, number, CrcValidationOptions) -> buffer } =
table.freeze({
-- `STORE` decompression method - No compression -- `STORE` decompression method - No compression
[0x00] = function(buf, validation) [0x00] = function(buf, _, validation)
validateCrc(buf, validation) validateCrc(buf, validation)
return buf return buf
end, end,
-- `DEFLATE` decompression method - Compressed raw deflate chunks -- `DEFLATE` decompression method - Compressed raw deflate chunks
[0x08] = function(buf, validation) [0x08] = function(buf, uncompressedSize, validation)
local decompressed = inflate(buf) -- FIXME: Why is uncompressedSize not getting inferred correctly although it
-- is typed?
local decompressed = inflate(buf, uncompressedSize :: any)
validateCrc(decompressed, validation) validateCrc(decompressed, validation)
return decompressed return decompressed
end, end,
@ -364,7 +367,7 @@ function ZipReader.extract(self: ZipReader, entry: ZipEntry, options: Extraction
error(`Unsupported compression, ID: {compressionMethod}`) error(`Unsupported compression, ID: {compressionMethod}`)
end end
content = decompress(content, { content = decompress(content, uncompressedSize, {
expected = crcChecksum, expected = crcChecksum,
skip = optionsOrDefault.skipCrcValidation, skip = optionsOrDefault.skipCrcValidation,
}) })