Skip to content

Commit f66d3dc

Browse files
JSCU-CNISchamper
andauthored
Add support for nested patterns in mimetype magic helper (#1615)
Co-authored-by: Schamper <1254028+Schamper@users.noreply.github.com>
1 parent a988dbc commit f66d3dc

File tree

6 files changed

+412
-381
lines changed

6 files changed

+412
-381
lines changed

dissect/target/helpers/magic/magic.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
MagicResult: TypeAlias = str | None
1212

1313

14+
WINDOW_CHUNK_SIZE = 4096
15+
16+
1417
class Magic:
1518
"""Magic is a helper class for identifying files to a file type by magic bytes.
1619
@@ -51,9 +54,28 @@ def detect(buf: BinaryIO, suffix: str | None = None, *, mime: bool = False) -> M
5154
raise TypeError("Provided suffix is not a string")
5255

5356
res_attr = "type" if mime else "name"
54-
for index, offset, magic in mimetypes.MAP:
55-
buf.seek(offset)
56-
if buf.read(len(magic)) == magic:
57+
58+
window = memoryview(bytearray(mimetypes.PATTERN_WINDOW_SIZE))
59+
window_size = 0
60+
61+
for offset, index, magic in mimetypes.MAP:
62+
end = offset + len(magic)
63+
if (overshoot := end - window_size) > 0:
64+
# The current window is not large enough to compare against the magic signature, read more bytes
65+
chunk = buf.read(
66+
min(
67+
((overshoot + WINDOW_CHUNK_SIZE - 1) // WINDOW_CHUNK_SIZE) * WINDOW_CHUNK_SIZE,
68+
mimetypes.PATTERN_WINDOW_SIZE - window_size,
69+
)
70+
)
71+
window[window_size : window_size + len(chunk)] = chunk
72+
window_size += len(chunk)
73+
74+
if window_size < end:
75+
# Not enough bytes to compare against the magic signature
76+
continue
77+
78+
if window[offset:end] == magic:
5779
return mimetypes.TYPES[index][res_attr]
5880

5981
if suffix:

dissect/target/helpers/magic/mimetypes/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
TYPES = []
77
MAP = set()
88
PATTERNS: set[tuple[int, tuple[str]]] = set()
9+
PATTERN_WINDOW_SIZE = 0
910

1011
files = [
1112
Path(__file__).parent.joinpath("freedesktop.py").resolve(),
@@ -42,4 +43,9 @@
4243
if "value" not in magic:
4344
raise ValueError(f"Magic definition missing value in {definition}")
4445

45-
MAP.add((i, magic.get("offset", 0), magic["value"]))
46+
offset = magic.get("offset", 0)
47+
value = magic["value"]
48+
MAP.add((offset, i, value))
49+
50+
if offset + len(value) > PATTERN_WINDOW_SIZE:
51+
PATTERN_WINDOW_SIZE = offset + len(value)

0 commit comments

Comments
 (0)