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

unreachable code paths need to be excluded from having coverage instrumentation #20992

Closed
andrewrk opened this issue Aug 8, 2024 · 0 comments · Fixed by #21236
Closed

unreachable code paths need to be excluded from having coverage instrumentation #20992

andrewrk opened this issue Aug 8, 2024 · 0 comments · Fixed by #21236
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. enhancement Solving this issue will likely involve adding new logic or components to the codebase. fuzzing
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Aug 8, 2024

Looking at the "if tower" example:

test "if tower" {
    const input_bytes = std.testing.fuzzInput(.{});
    if (input_bytes.len < 10) return;
    std.time.sleep(std.time.ns_per_ms / 3); // otherwise it finds the bug too fast!
    if (input_bytes[0] == 'A') {
        if (input_bytes[1] == 'l') {
            if (input_bytes[2] == 'e') {
                if (input_bytes[3] == 'x') {
                    if (input_bytes[4] == 'a') {
                        if (input_bytes[5] == 'n') {
                            if (input_bytes[6] == 'd') {
                                if (input_bytes[7] == 'r') {
                                    if (input_bytes[8] == 'a') {
                                        @panic("found bug");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

We see edges for every safety check:

image

We can access the raw pointer of the slices to escape the safety check, demonstrating that those edges disappear:

test "if tower" {
    const input_bytes = std.testing.fuzzInput(.{});
    if (input_bytes.len < 10) return;
    std.time.sleep(std.time.ns_per_ms / 3); // otherwise it finds the bug too fast!
    if (input_bytes.ptr[0] == 'A') {
        if (input_bytes.ptr[1] == 'l') {
            if (input_bytes.ptr[2] == 'e') {
                if (input_bytes.ptr[3] == 'x') {
                    if (input_bytes.ptr[4] == 'a') {
                        if (input_bytes.ptr[5] == 'n') {
                            if (input_bytes.ptr[6] == 'd') {
                                if (input_bytes.ptr[7] == 'r') {
                                    if (input_bytes.ptr[8] == 'a') {
                                        @panic("found bug");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

image

Those safety check edges are not interesting for code coverage because they are unreachable. The fuzzer still wants to know about any comparisons used which may have led to those unreachable branches, but we are not expecting to have code coverage for unreachable paths!

Fortunately, LLVM has a !nosanitize metadata node. Here is an example of using it on a branch:

  br i1 %19, label %cont, label %trap, !dbg !39, !nosanitize !28

...
!22 = distinct !DISubprogram(name: "main", scope: !2, file: !2, line: 2, type: !23, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !12, retainedNodes: !28)
...
!28 = !{}

So, the cmp should still have the instrumentation because it provides the cmp operands to the fuzzer, and the fuzzer is trying to find inputs that cause the unreachable path to be reached, but there should not be a PC edge annotation on the branch, because we'll know it got hit when the process panics and crashes!

@andrewrk andrewrk added enhancement Solving this issue will likely involve adding new logic or components to the codebase. backend-llvm The LLVM backend outputs an LLVM IR Module. fuzzing labels Aug 8, 2024
@andrewrk andrewrk added this to the 0.14.0 milestone Aug 8, 2024
andrewrk added a commit that referenced this issue Aug 19, 2024
work in progress commit that adds !nosanitize to all instructions.

output is wrong:

```
opt: /home/andy/dev/llvm-project-18/llvm/include/llvm/AsmParser/LLParser.h:93: bool llvm::ValID::operator<(const llvm::ValID&) const: Assertion `Kind == RHS.Kind && "Comparing ValIDs of different kinds"' failed.
    ()
    ()
```

working on #20992
andrewrk added a commit that referenced this issue Aug 21, 2024
see #20992

Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>
andrewrk added a commit that referenced this issue Aug 24, 2024
see #20992

Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>
andrewrk added a commit that referenced this issue Aug 27, 2024
see #20992

Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>
andrewrk added a commit that referenced this issue Aug 29, 2024
see #20992

Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend-llvm The LLVM backend outputs an LLVM IR Module. enhancement Solving this issue will likely involve adding new logic or components to the codebase. fuzzing
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant