Problem
Reachability, loop detection, and dominance all treat every block with no predecessors as an entry block. This marks unreachable code and metadata-created blocks as reachable.
Evidence
src/bytecode_analyzer.py:627-628 starts reachability from every value returned by _entry_blocks.
src/bytecode_analyzer.py:637-642 defines entries as all blocks with no predecessors, falling back to the first block only if none exist.
- Reproduction with bytecode
0x005b00 (STOP; JUMPDEST; STOP) currently reports both blocks reachable:
block_0000 pred=[] succ=[] reachable=True dead=False
block_0001 pred=[] succ=[] reachable=True dead=False
block_0001 cannot be reached from the bytecode entry point.
Why it matters
The analyzer disassembles full runtime bytecode and scans all JUMPDESTs. Solidity metadata or intentionally unreachable blocks can contain JUMPDEST bytes; treating them as entries pollutes reachability, dominance, loop metadata, and fallback/all-block TAC. This creates noisy model inputs and can hide genuinely dead code.
Suggested fix
Use the actual code entry point as the root for contract-level reachability. If function-level reachability is needed, compute it separately from identified dispatcher targets. Consider stripping CBOR metadata before CFG construction so metadata bytes cannot become pseudo-blocks.
Validation/tests to add
- Unit test for
STOP; JUMPDEST; STOP that marks the second block dead.
- Fixture with Solidity CBOR metadata containing
0x5b bytes to ensure metadata does not become reachable TAC.
- Regression tests that dominance/loop analysis do not use unreachable predecessorless blocks as roots.
Problem
Reachability, loop detection, and dominance all treat every block with no predecessors as an entry block. This marks unreachable code and metadata-created blocks as reachable.
Evidence
src/bytecode_analyzer.py:627-628starts reachability from every value returned by_entry_blocks.src/bytecode_analyzer.py:637-642defines entries as all blocks with no predecessors, falling back to the first block only if none exist.0x005b00(STOP; JUMPDEST; STOP) currently reports both blocks reachable:block_0001cannot be reached from the bytecode entry point.Why it matters
The analyzer disassembles full runtime bytecode and scans all
JUMPDESTs. Solidity metadata or intentionally unreachable blocks can containJUMPDESTbytes; treating them as entries pollutes reachability, dominance, loop metadata, and fallback/all-block TAC. This creates noisy model inputs and can hide genuinely dead code.Suggested fix
Use the actual code entry point as the root for contract-level reachability. If function-level reachability is needed, compute it separately from identified dispatcher targets. Consider stripping CBOR metadata before CFG construction so metadata bytes cannot become pseudo-blocks.
Validation/tests to add
STOP; JUMPDEST; STOPthat marks the second block dead.0x5bbytes to ensure metadata does not become reachable TAC.