Reject word sizes struct cannot express - #364
Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
Scope: 14 of the 183 p-code languages pypcode 4.0.1.dev0 exposes report a three-byte word — HCS-12, HCS12, HCS-12X, PIC-18, PIC-24E/F/H, dsPIC30F, dsPIC33C/E/F and the three extended AVR languages. All returned Caveats: Re-keyed 2026-08-28. The figures above were measured at |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/archinfo_364 |
6faa1ee to
6e59dcf
Compare
6e59dcf to
02d70fa
Compare
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Before — the format string comes back with a character archinfo masterAfter — the invalid size raises where it is asked for, and every size with this change |
struct_fmt() returned "Z" for a 3-byte word. That is not a struct format character, so every 24-bit architecture handed its callers a format string that raises "bad char in struct format" on use. struct has integer format characters for 1, 2, 4 and 8 bytes only and no way to describe a 3-byte integer, so report the size as invalid instead of inventing a character for it; such a word has to be assembled from bytes by the caller.
02d70fa to
a6e6c48
Compare
register_arch documents regexes as "str or SRE_Pattern", but the type check used re._pattern_type, which CPython removed in 3.7, so passing a compiled pattern raised AttributeError instead of registering the architecture. Use the public re.Pattern. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Rather than move the number with a disable comment, Verified against merge base
session: sharpen |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
Arch.struct_fmt()returns the format characterZfor a three-byte word, andstructhas no such character, so every caller that uses the string it hands back raises. It fires on the 14 of pypcode's 187 sleigh languages whose word is 24 bits — the PIC, dsPIC, HCS-12 and extended AVR families — and on any explicitstruct_fmt(size=3):The exception surfaces at the caller's
structcall, naming a format string the caller never wrote, rather than at the architecture that produced it.Root cause
archinfo/arch.pymaps size 3 to a characterstructdoes not define:structhas integer format characters for 1, 2, 4 and 8 bytes and nothing for 3, so no character can be correct here. Theelsebranch of the same chain already raises for 5, 6, 7 and 16; three bytes was the one invalid size that returned a value instead of raising.Fix
Delete the
size == 3branch so a three-byte word falls into the existingelse:The message names the size rather than claiming the argument must be a power of two, which the old text asserted and which this function never required. A caller that has to read a 24-bit word assembles it from bytes;
struct_fmtcannot do that for them, and the call is where saying so belongs. The docstring records the constraint so the next reader does not put a character back.Testing
tests/test_struct_fmt.pyasserts thatstruct.calcsize(arch.struct_fmt(size=n))equalsnfor every sizestructcan express, signed and unsigned, and that 0, 3, 5, 6, 7 and 16 raise.tests/test_pcode.py::test_struct_fmt_24bitpins the p-code case. Both fail on master, where the 24-bit call returns'>Z'andcalcsizerejects it.angr/cle#721 is the other half of this. Validation: #364 (comment)
sync: angr/cle#721
session: sharpen