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

internal/fuzz: do not write crashers to testdata in the module cache #48495

Closed
jayconrod opened this issue Sep 20, 2021 · 9 comments
Closed

internal/fuzz: do not write crashers to testdata in the module cache #48495

jayconrod opened this issue Sep 20, 2021 · 9 comments
Labels
FrozenDueToAge fuzz Issues related to native fuzzing support NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@jayconrod
Copy link
Contributor

When the fuzzing engine finds an input that causes an error in the fuzz function, it normally attempts to write that input to a file in testdata/fuzz/$target (where $target is the name of the fuzz target), relative to the package directory.

If this file can't be created, for example, because the package is part of the read-only module cache, go test -fuzz just prints the I/O error then exits. The user has no way to find out what the crashing input was.

go test -fuzz should ensure that these files are written somewhere. The fuzz cache is very likely to be writable since it's part of the build cache, so that would be a good location. go test -fuzz should print an alternative message, pointing to the newly written file. Unfortunately, it can't be used directly with go test -run.

@jayconrod jayconrod added NeedsFix The path to resolution is known, but the work has not been done. release-blocker fuzz Issues related to native fuzzing support labels Sep 20, 2021
@jayconrod jayconrod added this to the Go1.18 milestone Sep 20, 2021
@bcmills
Copy link
Contributor

bcmills commented Sep 20, 2021

If this file can't be created, for example, because the package is part of the read-only module cache,

Given the -modcacherw flag, we should probably avoid even trying to write to modules outside of the main module or workspace — it would be really confusing to see a recurring fuzz failure that doesn't reproduce on a clean machine.

@gopherbot
Copy link

Change https://golang.org/cl/359256 mentions this issue: cmd/go: test the interaction between the fuzz corpus and the module cache

@bcmills
Copy link
Contributor

bcmills commented Oct 27, 2021

I added a test illustrating the current behavior.

I see two or three options to fix the situation:

  1. We could add a flag (perhaps -test.fuzzdir?) to allow the caller of the test binary to specify an input/output directory, which would be read in addition to the default testdata/fuzz directory, but written instead of the default directory. Then go test -fuzz=. could explicitly set that flag to redirect or suppress output when fuzzing a package loaded from outside the main module(s).

    • This would require another change to the testing.testDeps interface, which may break tools that make assumptions about that interface. (Tools are not supposed to make assumptions about that interface, but some still do anyway.)
    • If we take this approach, should an input found during go test -fuzz=. cause the test to fail when run without the -fuzz flag? It seems surprising either way: either the fuzz crash isn't repeatable, or the non-fuzz behavior of the test depends on the state of the fuzz cache (not just the contents of the test's own module).
  2. We could add a flag (perhaps -test.fuzzsave=false?) to allow the caller of the test binary to suppress writes to the testdata directory, and have go test -fuzz=. set that flag.

    • This would reduce the usefulness of go test -fuzz outside the main module, but it would also be a bit simpler to explain and implement.
  3. We could make go test -fuzz explicitly fail for packages outside of the main module, punting this question to a later Go release (but allowing any of the possible behaviors).

@bcmills
Copy link
Contributor

bcmills commented Oct 27, 2021

I think I prefer option (3) for Go 1.18. If we reject go test -fuzz on any package outside the main module with a clear error message, then we can decide between (1) and (2) in a later release when we have a bit more breathing room.

@bcmills bcmills self-assigned this Oct 27, 2021
@gopherbot
Copy link

Change https://golang.org/cl/359414 mentions this issue: cmd/go: disallow the -fuzz flag for tests outside the main module

@bcmills bcmills changed the title internal/fuzz: handle I/O error writing crasher to testdata corpus internal/fuzz: do not write crashers to testdata in the module cache Oct 28, 2021
@katiehockman
Copy link
Contributor

Another couple options, both which still allow fuzzing in a different module:

  1. We could write the crash to the corpus cache instead (in $GOCACHE/fuzz). In the exit message, we can explain that fuzzing was run in a module outside the main one, and we didn't write the crash to testdata as a result.

  2. We could not write the crash anywhere, and just print it to the terminal instead. That's probably not the best option though, because the contents of the file might be massive.

I'm fine with punting this to 1.19 though.

@bcmills
Copy link
Contributor

bcmills commented Oct 28, 2021

(4) is, I think, basically equivalent to my (1). (go test could by default set -test.fuzzdir to $GOCACHE/fuzz, but could allow it to be overridden as well.)

The main issue I foresee with that approach is that it makes reproducibility tricky: it would either cause go test example.com/fuzzfail (without -fuzz=.) to fail all of the time, even when run from a pristine other module, or cause it to fail only when run within a specific other module (if we include the identity of the main module as part of the cache key), or cause it not to fail at all after a fuzzing failure is reported (which would be a surprising difference vs. fuzzing within a module), and clearing out the module cache and/or build cache might also have the side-effect of changing the non--fuzz behavior of the test.

(5) is my (2), but stated more concisely. 🙂

@gopherbot
Copy link

Change https://golang.org/cl/359481 mentions this issue: cmd/go: consolidate fuzz-support checks

gopherbot pushed a commit that referenced this issue Oct 28, 2021
We had been repeating conditions for specific platforms and
architectures to gate fuzzing tests, but the more of those tests we
add the more we will have to update if the set of supported platforms
and archictures expands over time.

We also ought to provide a friendlier error message when
'go test -fuzz' is used on non-supported platforms.

This change adds predicates in cmd/internal/sys, which already
contains similar predicates for related functionality (such as the
race detector), and uses those predicates in 'go test' and TestScript.

For #48495

Change-Id: If24c3997aeb4d201258e21e5b6cf4f7c08fbadd7
Reviewed-on: https://go-review.googlesource.com/c/go/+/359481
Trust: Bryan C. Mills <bcmills@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
@gopherbot
Copy link

Change https://golang.org/cl/359574 mentions this issue: cmd/go: document that test must not write to their source modules

gopherbot pushed a commit that referenced this issue Oct 29, 2021
Fixes #28386
Updates #48495

Change-Id: I76186077c7bbe3f8f608026ee1865de83fe169b4
Reviewed-on: https://go-review.googlesource.com/c/go/+/359574
Trust: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
@rsc rsc unassigned bcmills Jun 23, 2022
@golang golang locked and limited conversation to collaborators Jun 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge fuzz Issues related to native fuzzing support NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
Status: No status
Development

No branches or pull requests

5 participants