Skip to content

Commit 094aae4

Browse files
Merge pull request #4 from danila-schelkov/decompress-hotfix
fix(decompress): hash reading, comparing file MAGIC before decompression
2 parents 47d9136 + caea1a3 commit 094aae4

File tree

5 files changed

+38
-11
lines changed

5 files changed

+38
-11
lines changed

sc_compression/decompressor.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import lzma
22

3-
from sc_compression.signatures import Signatures, get_signature
3+
from sc_compression.exceptions import UnknownFileMagicException
4+
from sc_compression.signatures import Signatures, get_signature, MAGIC_SC, MAGIC_ZSTD, MAGIC_SCLZ
45
from sc_compression.utils.reader import Reader
56

67
try:
@@ -34,24 +35,29 @@ def decompress(self, buffer: bytes) -> bytes:
3435
if self.signature == Signatures.SC:
3536
reader = Reader(buffer, "big")
3637

37-
reader.read(2)
38+
self.check_magic(MAGIC_SC, reader=reader)
39+
3840
self.file_version = reader.read_int32()
3941
if self.file_version == 4:
4042
self.file_version = reader.read_int32()
41-
elif self.file_version == 0x05000000:
43+
44+
if self.file_version == 0x05000000:
4245
reader.endian = "little"
4346

4447
metadata_table_offset = reader.read_int32() # offset to metadata vtable
4548
reader.read(metadata_table_offset) # metadata
4649
else:
4750
hash_length = reader.read_int32()
4851
self.hash = reader.read(hash_length)
52+
4953
return self.decompress(buffer[reader.tell() :])
5054
elif self.signature == Signatures.SIG:
5155
return self.decompress(buffer[68:])
5256
elif self.signature == Signatures.SCLZ and lzham is not None:
5357
reader = Reader(buffer, "little")
54-
reader.read(4)
58+
59+
self.check_magic(MAGIC_SCLZ, reader=reader)
60+
5561
dict_size_log2 = reader.read_u_int8()
5662
uncompressed_size = reader.read_int32()
5763

@@ -64,9 +70,21 @@ def decompress(self, buffer: bytes) -> bytes:
6470
compressed = buffer[:5] + b"\xff" * 8 + buffer[9:]
6571
return decompressor.decompress(compressed)
6672
elif self.signature == Signatures.ZSTD and zstandard is not None:
67-
# the decompress.decompress() API errors with zstd.ZstdError: could not
68-
# determine content size in frame header
73+
self.check_magic(MAGIC_ZSTD, buffer=buffer)
74+
6975
decompressor = zstandard.ZstdDecompressor()
7076
return decompressor.decompress(buffer)
7177
else:
7278
raise TypeError(self.signature)
79+
80+
@staticmethod
81+
def check_magic(expected_magic: bytes, reader: Reader | None = None, buffer: bytes | None = None) -> None:
82+
if reader is not None:
83+
magic = reader.read(len(expected_magic))
84+
elif buffer is not None:
85+
magic = buffer[:len(expected_magic)]
86+
else:
87+
raise Exception("Cannot find buffer to get magic from.")
88+
89+
if magic != expected_magic:
90+
raise UnknownFileMagicException(magic, magic, expected_magic)

sc_compression/exceptions/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .unknown_file_magic import UnknownFileMagicException
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class UnknownFileMagicException(Exception):
2+
def __init__(self, magic: bytes, expected_magic: bytes, *args):
3+
super().__init__(f"Unknown file magic: {magic.hex()}, while expected was {expected_magic.hex()}", *args)

sc_compression/signatures.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import re
22
from enum import Enum
33

4+
MAGIC_SC = b"SC"
5+
MAGIC_SCLZ = b"SCLZ"
6+
MAGIC_SIG = b"Sig:"
7+
MAGIC_ZSTD = b"\x28\xb5\x2f\xfd"
8+
49

510
class Signatures(Enum):
611
NONE = 0
@@ -16,14 +21,14 @@ def get_signature(buffer: bytes) -> Signatures:
1621

1722
if re.match(b"\x00\x00?\x00", buffer[1:5]):
1823
signature = Signatures.LZMA
19-
elif buffer.startswith(b"\x28\xb5\x2f\xfd"):
24+
elif buffer.startswith(MAGIC_ZSTD):
2025
signature = Signatures.ZSTD
2126

22-
if buffer.startswith(b"SCLZ"):
27+
if buffer.startswith(MAGIC_SCLZ):
2328
signature = Signatures.SCLZ
24-
elif buffer.startswith(b"SC"):
29+
elif buffer.startswith(MAGIC_SC):
2530
signature = Signatures.SC
26-
elif buffer.startswith(b"Sig:"):
31+
elif buffer.startswith(MAGIC_SIG):
2732
signature = Signatures.SIG
2833

2934
return signature

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setuptools.setup(
1010
name="sc-compression",
11-
version="0.6.4",
11+
version="0.6.5",
1212
author="Vorono4ka",
1313
author_email="[email protected]",
1414
description="SC Compression",

0 commit comments

Comments
 (0)