Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(invariant): Support coverage-guided fuzzing #8665

Open
QiuhaoLi opened this issue Aug 14, 2024 · 3 comments
Open

feat(invariant): Support coverage-guided fuzzing #8665

QiuhaoLi opened this issue Aug 14, 2024 · 3 comments
Labels
A-testing Area: testing C-forge Command: forge Cmd-forge-test Command: forge test T-feature Type: feature T-post-V1 Area: to tackle after V1

Comments

@QiuhaoLi
Copy link

Component

Forge

Describe the feature you would like

Currently, the forge fuzz testing and invariant testing don’t support coverage-guided fuzzing, which could generally improve the fuzzing performance. The forge fuzzer can’t find the correct sequence B(2)->C(3)->A(1)->D(4) with 10000 runs for the code below:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";

contract Puzzle {
    uint256 private counter;
    bool public hacked; // B(2)->C(3)->A(1)->D(4)

    function A(uint256 x) external {
        if (counter == 2 && x == 1) counter++; else counter = 0;
    }
    function B(uint256 x) external {
        if (counter == 0 && x == 2) counter++;
    }
    function C(uint256 x) external {
        if (counter == 1 && x == 3) counter++; else counter = 0;
    }
    function D(uint256 x) external {
        if (counter == 3 && x == 4) hacked = true; else counter = 0;
    }
}
contract CounterTest is Test {
    Puzzle public puzzle;

    function setUp() public {
        puzzle = new Puzzle();
    }
/// forge-config: default.invariant.runs = 10000
    function invariant_Puzzle() view external {
        assertEq(puzzle.hacked(), false);
    }
}

If it’s coverage-guided and will store and mutate the previous sequences, the final sequence will be solved step by step like B(2)->X->X->X, B(2)->C(3)->X->X, …, B(2)->C(3)->A(1)->D(4).

For example, we can make two strategies: 1. Random Generator (the current one, 50%). 2. Coverage-guided (50%).

If the coverage-guided strategy is picked up, pop a sequence from the new coverage sequence deque and mutate on it (mutate on calldata is ignored here):

  1. Insert a new random tx. 50%
  2. Exchange two txs’ positions. 20%
  3. Repeat a tx. 20%
  4. Change a tx’s msg.value. 10%
  5. Increase the mutate count of the sequence; if the count > 100, delete it from the deque; otherwise, push it back to the deque.

After getting the new mutated sequence:

  1. Get the coverage before a sequence is executed.
  2. Get the coverage after a sequence is executed.
  3. If there is a new contract or new code hit (we don’t consider the hit number or path for now). Shrink the sequence to a smaller one that triggers the same coverage and push it into the new coverage deque.
  4. The new coverage sequence deque has a max size of 64MB (configable?). And the sequence max length is 64 (configable?).

Additional context

No response

@QiuhaoLi QiuhaoLi added T-feature Type: feature T-needs-triage Type: this issue needs to be labelled labels Aug 14, 2024
@QiuhaoLi
Copy link
Author

@grandizzy @klkvr for your thoughts on this :)

@zerosnacks zerosnacks added A-testing Area: testing Cmd-forge-test Command: forge test C-forge Command: forge and removed T-needs-triage Type: this issue needs to be labelled labels Aug 16, 2024
@zerosnacks zerosnacks added this to the v1.0.0 milestone Aug 16, 2024
@a-t-0
Copy link

a-t-0 commented Sep 19, 2024

@QiuhaoLi Thank you for suggesting such a wonderful strategy, I was not aware coverage guided fuzzing would be possible. I would be quite happy with such a feature.

@grandizzy
Copy link
Collaborator

@grandizzy @klkvr for your thoughts on this :)

sorry for late reply. this will be a great improvement, but IMO at this point we cannot really rely on coverage due to it's limitations (not reliable if running with optimizations / via-ir). We have plans to rewrite coverage mechanism post 1.0 release and adding suggested coverage-guided fuzzing.

@grandizzy grandizzy removed this from the v1.0.0 milestone Sep 26, 2024
@jenpaff jenpaff added this to Foundry Sep 30, 2024
@jenpaff jenpaff moved this to Todo in Foundry Sep 30, 2024
@jenpaff jenpaff added the T-post-V1 Area: to tackle after V1 label Sep 30, 2024
@jenpaff jenpaff moved this from Blocked to Todo in Foundry Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testing Area: testing C-forge Command: forge Cmd-forge-test Command: forge test T-feature Type: feature T-post-V1 Area: to tackle after V1
Projects
Archived in project
Development

No branches or pull requests

5 participants