Skip to content

Commit 0173951

Browse files
committed
Add support for flipped endianness (#3420)
1 parent 78ef8b7 commit 0173951

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

polyfile/magic.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,6 +2064,22 @@ def match(self, data: bytes, expected: NumericValue) -> DataTypeMatch:
20642064
else:
20652065
return DataTypeMatch.INVALID
20662066

2067+
def flip_endianness(self) -> "NumericDataType":
2068+
"""Return a copy with LITTLE/BIG endianness flipped."""
2069+
if self.endianness == Endianness.LITTLE:
2070+
new_endianness = Endianness.BIG
2071+
elif self.endianness == Endianness.BIG:
2072+
new_endianness = Endianness.LITTLE
2073+
else:
2074+
new_endianness = self.endianness # NATIVE and PDP unchanged
2075+
return NumericDataType(
2076+
name=self.name,
2077+
base_type=self.base_type,
2078+
unsigned=self.unsigned,
2079+
endianness=new_endianness,
2080+
preprocess=self.preprocess
2081+
)
2082+
20672083
@staticmethod
20682084
def parse(fmt: str) -> "NumericDataType":
20692085
name = fmt
@@ -2151,6 +2167,25 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
21512167
message=f"expected {self.constant!s}"
21522168
)
21532169

2170+
def test_flip_endianness(
2171+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2172+
) -> TestResult:
2173+
if isinstance(self.data_type, NumericDataType):
2174+
data_type = self.data_type.flip_endianness()
2175+
else:
2176+
data_type = self.data_type
2177+
match = data_type.match(data[absolute_offset:], self.constant)
2178+
if match:
2179+
return MatchedTest(self, offset=absolute_offset + match.initial_offset, length=len(match.raw_match),
2180+
value=match.value, parent=parent_match)
2181+
else:
2182+
return FailedTest(
2183+
self,
2184+
offset=absolute_offset,
2185+
parent=parent_match,
2186+
message=f"expected {self.constant!s}"
2187+
)
2188+
21542189

21552190
class OffsetMatchTest(MagicTest):
21562191
def __init__(
@@ -2179,6 +2214,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
21792214
message=f"expected {self.value!r}"
21802215
)
21812216

2217+
def test_flip_endianness(
2218+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2219+
) -> TestResult:
2220+
return self.test(data, absolute_offset, parent_match)
2221+
21822222

21832223
class IndirectResult(MatchedTest):
21842224
def __init__(self, test: "IndirectTest", offset: int, parent: Optional[TestResult] = None):
@@ -2228,6 +2268,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
22282268
absolute_offset += parent_match.offset
22292269
return IndirectResult(self, absolute_offset, parent_match)
22302270

2271+
def test_flip_endianness(
2272+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2273+
) -> TestResult:
2274+
return self.test(data, absolute_offset, parent_match)
2275+
22312276

22322277
class NamedTest(MagicTest):
22332278
def __init__(
@@ -2353,6 +2398,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
23532398
def subtest_type(self) -> TestType:
23542399
return TestType.TEXT
23552400

2401+
def test_flip_endianness(
2402+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2403+
) -> TestResult:
2404+
return self.test(data, absolute_offset, parent_match)
2405+
23562406

23572407
class CSVTest(MagicTest):
23582408
def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]) -> TestResult:
@@ -2392,6 +2442,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
23922442
def subtest_type(self) -> TestType:
23932443
return TestType.TEXT
23942444

2445+
def test_flip_endianness(
2446+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2447+
) -> TestResult:
2448+
return self.test(data, absolute_offset, parent_match)
2449+
23952450

23962451
class DefaultTest(MagicTest):
23972452
def subtest_type(self) -> TestType:
@@ -2404,6 +2459,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
24042459
return FailedTest(self, offset=absolute_offset, parent=parent_match, message="the parent test already "
24052460
"has a child that matched")
24062461

2462+
def test_flip_endianness(
2463+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2464+
) -> TestResult:
2465+
return self.test(data, absolute_offset, parent_match)
2466+
24072467

24082468
class ClearTest(MagicTest):
24092469
def subtest_type(self) -> TestType:
@@ -2416,6 +2476,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
24162476
parent_match.child_matched = False
24172477
return MatchedTest(self, offset=absolute_offset, length=0, parent=parent_match, value=None)
24182478

2479+
def test_flip_endianness(
2480+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2481+
) -> TestResult:
2482+
return self.test(data, absolute_offset, parent_match)
2483+
24192484

24202485
class DERTest(MagicTest):
24212486
def subtest_type(self) -> TestType:
@@ -2426,6 +2491,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
24262491
"TODO: Implement support for the DER test (e.g., using the Kaitai asn1_der.py parser)"
24272492
)
24282493

2494+
def test_flip_endianness(
2495+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2496+
) -> TestResult:
2497+
return self.test(data, absolute_offset, parent_match)
2498+
24292499

24302500
class PlainTextTest(MagicTest):
24312501
AUTO_REGISTER_TEST = False
@@ -2469,6 +2539,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
24692539
return FailedTest(self, offset=absolute_offset, parent=parent_match, message="the data do not appear to "
24702540
"be encoded in a text format")
24712541

2542+
def test_flip_endianness(
2543+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2544+
) -> TestResult:
2545+
return self.test(data, absolute_offset, parent_match)
2546+
24722547

24732548
class OctetStreamTest(MagicTest):
24742549
AUTO_REGISTER_TEST = False
@@ -2492,6 +2567,11 @@ def test(self, data: bytes, absolute_offset: int, parent_match: Optional[TestRes
24922567
return MatchedTest(self, offset=absolute_offset, length=len(data) - absolute_offset, parent=parent_match,
24932568
value=data)
24942569

2570+
def test_flip_endianness(
2571+
self, data: bytes, absolute_offset: int, parent_match: Optional[TestResult]
2572+
) -> TestResult:
2573+
return self.test(data, absolute_offset, parent_match)
2574+
24952575

24962576
TEST_PATTERN: Pattern[str] = re.compile(
24972577
r"^(?P<level>[>]*)(?P<offset>[^\s!][^\s]*)\s+(?P<data_type>[^\s]+)\s+(?P<remainder>.+)$"

0 commit comments

Comments
 (0)