feat: add extraction version validation to ZipReader:extract

This commit is contained in:
Erica Marigold 2025-01-10 07:38:40 +00:00
parent 3956120328
commit 3d2e3697fb
Signed by: DevComp
GPG key ID: 429EF1C337871656

View file

@ -2,6 +2,9 @@ local inflate = require("./inflate")
local validateCrc = require("./utils/validate_crc") local validateCrc = require("./utils/validate_crc")
local path = require("./utils/path") local path = require("./utils/path")
-- The maximum supported PKZIP format specification version that we support
local MAX_SUPPORTED_PKZIP_VERSION = 63
-- Little endian constant signatures used in the ZIP file format -- Little endian constant signatures used in the ZIP file format
local SIGNATURES = table.freeze({ local SIGNATURES = table.freeze({
-- Marks the beginning of each file in the ZIP -- Marks the beginning of each file in the ZIP
@ -37,6 +40,7 @@ local DECOMPRESSION_ROUTINES: { [number]: { name: CompressionMethod, decompress:
}, },
} }
-- Set of placeholder entry properties for incompatible entries
local EMPTY_PROPERTIES: ZipEntryProperties = table.freeze({ local EMPTY_PROPERTIES: ZipEntryProperties = table.freeze({
versionMadeBy = 0, versionMadeBy = 0,
compressedSize = 0, compressedSize = 0,
@ -46,6 +50,7 @@ local EMPTY_PROPERTIES: ZipEntryProperties = table.freeze({
crc = 0, crc = 0,
}) })
-- Lookup table for the OS that created the ZIP
local MADE_BY_OS_LOOKUP: { [number]: MadeByOS } = { local MADE_BY_OS_LOOKUP: { [number]: MadeByOS } = {
[0x0] = "FAT", [0x0] = "FAT",
[0x1] = "AMIGA", [0x1] = "AMIGA",
@ -441,6 +446,7 @@ function ZipReader.extract(self: ZipReader, entry: ZipEntry, options: Extraction
-- Local File Header format: -- Local File Header format:
-- Offset Bytes Description -- Offset Bytes Description
-- 0 4 Local file header signature -- 0 4 Local file header signature
-- 4 2 Version needed to extract
-- 6 2 General purpose bitflags -- 6 2 General purpose bitflags
-- 8 2 Compression method (8 = DEFLATE) -- 8 2 Compression method (8 = DEFLATE)
-- 14 4 CRC32 checksum -- 14 4 CRC32 checksum
@ -479,6 +485,10 @@ function ZipReader.extract(self: ZipReader, entry: ZipEntry, options: Extraction
error("Invalid local file header") error("Invalid local file header")
end end
-- Validate that the version needed to extract is supported
local versionNeeded = buffer.readu16(self.data, pos + 4)
assert(MAX_SUPPORTED_PKZIP_VERSION >= versionNeeded, `Unsupported PKZip spec version: {versionNeeded}`)
local bitflags = buffer.readu16(self.data, pos + 6) local bitflags = buffer.readu16(self.data, pos + 6)
local crcChecksum = buffer.readu32(self.data, pos + 14) local crcChecksum = buffer.readu32(self.data, pos + 14)
local compressedSize = buffer.readu32(self.data, pos + 18) local compressedSize = buffer.readu32(self.data, pos + 18)