feat(edge_cov): add CmpLog-style comparison operand tracking#397
feat(edge_cov): add CmpLog-style comparison operand tracking#397grandizzy wants to merge 1 commit intoparadigmxyz:mainfrom
Conversation
Add comparison operand logging to EdgeCovInspector for CmpLog-style guided fuzzing. This captures operands from EQ, LT, GT, SLT, SGT, and ISZERO opcodes to help fuzzers solve comparison constraints. Changes: - Add CmpOperands struct to store comparison operand pairs with PC - Add cmp_log field to EdgeCovInspector - Add get_cmp_log() and into_parts() accessor methods - Modify reset() to clear cmp_log alongside hitcount - Add store_cmp() and do_cmp_step() for capturing comparison operands - Track comparison opcodes in step() inspector method This enables coverage-guided fuzzers like Foundry to extract comparison values and synthesize inputs that satisfy tight constraints like `a == 61 * b` by observing the actual operand values at runtime. Inspired by AFL++'s CmpLog feature for solving magic byte comparisons.
|
@0xalpharush could you please have a look at this PR, it helped quite a lot for breaking new invariants in maze (need to make use of it in foundry). Thanks! |
|
This make sense. Looking at LibAFL, it does seem they try to determine if the value is constant or variable as well as if the comparison is the loop counter. It's also worth noting the usage should likely be able to track how the the comparison logs change between the original and mutated input as that is used to inform mutations. That is, if modifying the input does not change a comparison, it means the fuzzer input isn't directly read and either relies on some computation or state. In practice, I suspsect cmplog for EVM would be most useful when a slice of the calldata is directly read in a comparison and we can replace the right portion of bytes to solve the branch I wonder if some of the stack dictionary stuff in Foundry can use this logic as well. Would appreciate a ping when the integration is made as well. |
Summary
Add comparison operand logging to
EdgeCovInspectorfor CmpLog-style guided fuzzing. This captures operands from EQ, LT, GT, SLT, SGT, and ISZERO opcodes to help fuzzers solve comparison constraints.Motivation
Coverage-guided fuzzers struggle with tight constraints like
a == 61 * bbecause they sample parameters independently. By capturing the actual comparison operands at runtime, fuzzers can:This is inspired by AFL++'s CmpLog feature.
Changes
CmpOperandsstruct to store comparison operand pairs with PCcmp_logfield toEdgeCovInspectorget_cmp_log()andinto_parts()accessor methodsreset()to clear cmp_log alongside hitcountstore_cmp()anddo_cmp_step()for capturing comparison operandsstep()inspector methodTesting
Added 4 unit tests:
test_cmp_log_basic- Verifies CmpLog captures comparison operands from a real contracttest_cmp_log_into_parts- Tests theinto_parts()methodtest_cmp_log_reset- Verifiesreset()clears both hitcount and cmp_logtest_cmp_operands_struct- Tests CmpOperands struct creation, Default, CloneUsage