Skip to content

Commit 87ccbea

Browse files
committed
fix(handlers): fix infinite loop in zstd handler.
Given an invalid or truncated zstd file, unblob/handlers/compression/zstd.py, in calculate_chunk(), did not check for EOF in the while loop. After reaching EOF, it always "reads" a block of type 0 and of size 0. This is a valid block type (i.e. no raised exception) but not an "end block" type, which is the only other condition to exit the loop. Therefore, it kept looping actively and never returned. Since we're reading from an mmap'ed file, reading from the file after reaching EOF does not trigger an exception. Fixed by checking if the read value is not empty and yielding an InvalidInputFormat exception otherwise. An integration test case reproducing the infinite loop has been added to zstd test cases (truncated.dos.zstd).
1 parent 3733fb3 commit 87ccbea

File tree

3 files changed

+8
-3
lines changed

3 files changed

+8
-3
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:052ba0688dc57289ad3bb5863ac952b4ff8d91156e3a3a274e60ef2ad1746015
3+
size 9

tests/integration/compression/zstd/__output__/truncated.dos.zstd_extract/.gitkeep

Whitespace-only changes.

unblob/handlers/compression/zstd.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ def calculate_chunk(self, file: File, start_offset: int) -> Optional[ValidChunk]
5858

5959
last_block = False
6060
while not last_block:
61-
block_header = int.from_bytes(
62-
file.read(BLOCK_HEADER_LEN), byteorder="little"
63-
)
61+
block_header_val = file.read(BLOCK_HEADER_LEN)
62+
# EOF
63+
if not block_header_val:
64+
raise InvalidInputFormat("Premature end of ZSTD stream.")
65+
block_header = int.from_bytes(block_header_val, byteorder="little")
6466
last_block = block_header >> 0 & 0b1
6567
block_type = block_header >> 1 & 0b11
6668

0 commit comments

Comments
 (0)