// Copyright 2020 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.//go:build darwin || freebsd || linuxpackage fuzzimport ()type sharedMemSys struct{}func sharedMemMapFile( *os.File, int, bool) (*sharedMem, error) { := syscall.PROT_READ | syscall.PROT_WRITE := syscall.MAP_FILE | syscall.MAP_SHARED , := syscall.Mmap(int(.Fd()), 0, , , )if != nil {returnnil, }return &sharedMem{f: , region: , removeOnClose: }, nil}// Close unmaps the shared memory and closes the temporary file. If this// sharedMem was created with sharedMemTempFile, Close also removes the file.func ( *sharedMem) () error {// Attempt all operations, even if we get an error for an earlier operation. // os.File.Close may fail due to I/O errors, but we still want to delete // the temporary file.var []error = append(,syscall.Munmap(.region), .f.Close())if .removeOnClose { = append(, os.Remove(.f.Name())) }for , := range {if != nil {return } }returnnil}// setWorkerComm configures communication channels on the cmd that will// run a worker process.func setWorkerComm( *exec.Cmd, workerComm) { := <-.memMu := .f .memMu <- .ExtraFiles = []*os.File{.fuzzIn, .fuzzOut, }}// getWorkerComm returns communication channels in the worker process.func getWorkerComm() ( workerComm, error) { := os.NewFile(3, "fuzz_in") := os.NewFile(4, "fuzz_out") := os.NewFile(5, "fuzz_mem") , := .Stat()if != nil {returnworkerComm{}, } := int(.Size())ifint64() != .Size() {returnworkerComm{}, fmt.Errorf("fuzz temp file exceeds maximum size") } := false , := sharedMemMapFile(, , )if != nil {returnworkerComm{}, } := make(chan *sharedMem, 1) <- returnworkerComm{fuzzIn: , fuzzOut: , memMu: }, nil}// isInterruptError returns whether an error was returned by a process that// was terminated by an interrupt signal (SIGINT).func isInterruptError( error) bool { , := .(*exec.ExitError)if ! || .ExitCode() >= 0 {returnfalse } := .Sys().(syscall.WaitStatus)return .Signal() == syscall.SIGINT}// terminationSignal checks if err is an exec.ExitError with a signal status.// If it is, terminationSignal returns the signal and true.// If not, -1 and false.func terminationSignal( error) (os.Signal, bool) { , := .(*exec.ExitError)if ! || .ExitCode() >= 0 {returnsyscall.Signal(-1), false } := .Sys().(syscall.WaitStatus)return .Signal(), .Signaled()}// isCrashSignal returns whether a signal was likely to have been caused by an// error in the program that received it, triggered by a fuzz input. For// example, SIGSEGV would be received after a nil pointer dereference.// Other signals like SIGKILL or SIGHUP are more likely to have been sent by// another process, and we shouldn't record a crasher if the worker process// receives one of these.//// Note that Go installs its own signal handlers on startup, so some of these// signals may only be received if signal handlers are changed. For example,// SIGSEGV is normally transformed into a panic that causes the process to exit// with status 2 if not recovered, which we handle as a crash.func isCrashSignal( os.Signal) bool {switch {casesyscall.SIGILL, // illegal instructionsyscall.SIGTRAP, // breakpointsyscall.SIGABRT, // abort() calledsyscall.SIGBUS, // invalid memory access (e.g., misaligned address)syscall.SIGFPE, // math error, e.g., integer divide by zerosyscall.SIGSEGV, // invalid memory access (e.g., write to read-only)syscall.SIGPIPE: // sent data to closed pipe or socketreturntruedefault:returnfalse }}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.