aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dvyukov
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/dvyukov
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/dvyukov')
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/LICENSE174
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/cover.go908
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/main.go904
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-defs/defs.go36
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/cover.go22
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/doc.go10
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go99
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main_libFuzzer.go20
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sonar.go201
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_posix.go32
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_windows.go56
-rw-r--r--vendor/github.com/dvyukov/go-fuzz/internal/go-fuzz-types/types.go28
12 files changed, 0 insertions, 2490 deletions
diff --git a/vendor/github.com/dvyukov/go-fuzz/LICENSE b/vendor/github.com/dvyukov/go-fuzz/LICENSE
deleted file mode 100644
index dd5b3a58a..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/LICENSE
+++ /dev/null
@@ -1,174 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/cover.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/cover.go
deleted file mode 100644
index edafad179..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/cover.go
+++ /dev/null
@@ -1,908 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "bytes"
- "crypto/sha1"
- "fmt"
- "go/ast"
- "go/constant"
- "go/printer"
- "go/token"
- "go/types"
- "io"
- "strconv"
- "strings"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
- . "github.com/dvyukov/go-fuzz/internal/go-fuzz-types"
-)
-
-const fuzzdepPkg = "_go_fuzz_dep_"
-
-func instrument(pkg, fullName string, fset *token.FileSet, parsedFile *ast.File, info *types.Info, out io.Writer, blocks *[]CoverBlock, sonar *[]CoverBlock) {
- file := &File{
- fset: fset,
- pkg: pkg,
- fullName: fullName,
- astFile: parsedFile,
- blocks: blocks,
- info: info,
- }
- if sonar == nil {
- file.addImport("go-fuzz-dep", fuzzdepPkg, "CoverTab")
- ast.Walk(file, file.astFile)
- } else {
- s := &Sonar{
- fset: fset,
- fullName: fullName,
- pkg: pkg,
- blocks: sonar,
- info: info,
- }
- ast.Walk(s, file.astFile)
- }
-
- file.print(out)
-}
-
-type Sonar struct {
- fset *token.FileSet
- fullName string
- pkg string
- blocks *[]CoverBlock
- info *types.Info
-}
-
-var sonarSeq = 0
-
-func (s *Sonar) Visit(n ast.Node) ast.Visitor {
- // TODO: detect "x&mask==0", emit sonar(x, x&^mask)
- switch nn := n.(type) {
- case *ast.BinaryExpr:
- break
-
- case *ast.GenDecl:
- if nn.Tok != token.VAR {
- return nil // constants and types are not interesting
- }
- return s
-
- case *ast.SelectorExpr:
- return nil
-
- case *ast.SwitchStmt:
- if nn.Tag == nil || nn.Body == nil {
- return s // recurse
- }
- // Replace:
- // switch a := foo(); bar(a) {
- // case x: ...
- // case y: ...
- // }
- // with:
- // switch {
- // default:
- // a := foo()
- // __tmp := bar(a)
- // switch {
- // case __tmp == x: ...
- // case __tmp == y: ...
- // }
- // }
- // The == comparisons will be instrumented later when we recurse.
- sw := new(ast.SwitchStmt)
- *sw = *nn
- var stmts []ast.Stmt
- if sw.Init != nil {
- stmts = append(stmts, sw.Init)
- sw.Init = nil
- }
- const tmpvar = "__go_fuzz_tmp"
- tmp := ast.NewIdent(tmpvar)
- typ := s.info.Types[sw.Tag]
- s.info.Types[tmp] = typ
- stmts = append(stmts, &ast.AssignStmt{Lhs: []ast.Expr{tmp}, Tok: token.DEFINE, Rhs: []ast.Expr{sw.Tag}})
- stmts = append(stmts, &ast.AssignStmt{Lhs: []ast.Expr{ast.NewIdent("_")}, Tok: token.ASSIGN, Rhs: []ast.Expr{tmp}})
- sw.Tag = nil
- stmts = append(stmts, sw)
- for _, cas1 := range sw.Body.List {
- cas := cas1.(*ast.CaseClause)
- for i, expr := range cas.List {
- tmp := &ast.Ident{Name: tmpvar, NamePos: expr.Pos()}
- s.info.Types[tmp] = typ
- cas.List[i] = &ast.BinaryExpr{X: tmp, Op: token.EQL, Y: expr}
- }
- }
- nn.Tag = nil
- nn.Init = nil
- nn.Body = &ast.BlockStmt{List: []ast.Stmt{&ast.CaseClause{Body: stmts}}}
- return s // recurse
-
- case *ast.ForStmt:
- // For condition is usually uninteresting, but produces lots of samples.
- // So we skip it if it looks boring.
- if nn.Init != nil {
- ast.Walk(s, nn.Init)
- }
- if nn.Post != nil {
- ast.Walk(s, nn.Post)
- }
- ast.Walk(s, nn.Body)
- if nn.Cond != nil {
- // Look for the following pattern:
- // for foo := ...; foo ? ...; ... { ... }
- boring := false
- if nn.Init != nil {
- if init, ok1 := nn.Init.(*ast.AssignStmt); ok1 && init.Tok == token.DEFINE && len(init.Lhs) == 1 {
- if id, ok2 := init.Lhs[0].(*ast.Ident); ok2 {
- if bex, ok3 := nn.Cond.(*ast.BinaryExpr); ok3 {
- if x, ok4 := bex.X.(*ast.Ident); ok4 && x.Name == id.Name {
- boring = true
- }
- if x, ok4 := bex.Y.(*ast.Ident); ok4 && x.Name == id.Name {
- boring = true
- }
- }
- }
- }
- }
- if !boring {
- ast.Walk(s, nn.Cond)
- }
- }
- return nil
-
- default:
- return s // recurse
- }
-
- // TODO: handle map index expressions (especially useful for strings).
- // E.g. when code matches a read in identifier against a set of known identifiers.
- // For the record, it looks as follows. However, it is tricky to distinguish
- // from slice/array index and map assignments...
- //. . . . . . . *ast.IndexExpr {
- //. . . . . . . . X: *ast.Ident {
- //. . . . . . . . . Name: "m"
- //. . . . . . . . }
- //. . . . . . . . Index: *ast.Ident {
- //. . . . . . . . . Name: "s"
- //. . . . . . . . }
- //. . . . . . . }
-
- // TODO: transform expressions so that lhs expression contains a variable
- // and rhs contains all constant operands. For example, for (real code from vp8 codec):
- // cf := (b[0]>>4)&7 == 5
- // we would like to transform it to:
- // b[0] & (7<<4) == 5<<4
- // and then to:
- // b[0] == 5<<4 | b & ^(7<<4)
- // and emit:
- // Sonar(b[0], 5<<4 | b & ^(7<<4), SonarEQL)
- // This will allow the fuzzer to figure out what bytes it needs to replace
- // with what bytes in order to crack this condition.
- // Similarly, for:
- // x/3 == 100
- // we would like to emit:
- // Sonar(x, 100*3, SonarEQL)
-
- // TODO: intercept strings.Index/HasPrefix and similar functions.
-
- nn := n.(*ast.BinaryExpr)
- var flags uint8
- switch nn.Op {
- case token.EQL:
- flags = SonarEQL
- break
- case token.NEQ:
- flags = SonarNEQ
- break
- case token.LSS:
- flags = SonarLSS
- break
- case token.GTR:
- flags = SonarGTR
- break
- case token.LEQ:
- flags = SonarLEQ
- break
- case token.GEQ:
- flags = SonarGEQ
- break
- default:
- return s // recurse
- }
- // Replace:
- // x != y
- // with:
- // func() _go_fuzz_dep_.Bool { v1 := x; v2 := y; go-fuzz-dep.Sonar(v1, v2, flags); return v1 != v2 }() == true
- // Using "== true" lets us modify the AST Node in-place.
- v1 := nn.X
- v2 := nn.Y
- ast.Walk(s, v1)
- ast.Walk(s, v2)
- if isCap(v1) || isCap(v2) {
- // Haven't seen useful cases yet.
- return s
- }
- if isLen(v1) || isLen(v2) {
- // TODO: we could pass both length value and the len argument.
- // For example, if the code is:
- // name := ... // obtained from input
- // if len(name) > 5 { ... }
- // If we would have the name value at runtime, we will know
- // what part of the input to alter to affect len result.
- flags |= SonarLength
- }
-
- checkType := func(tv types.TypeAndValue) bool {
- // Comparisons of pointers, maps, chans and bool are not interesting.
- if _, ok := tv.Type.(*types.Pointer); ok {
- return false
- }
- if _, ok := tv.Type.(*types.Map); ok {
- return false
- }
- if _, ok := tv.Type.(*types.Chan); ok {
- return false
- }
- s := tv.Type.Underlying().String()
- if s == "bool" || s == "ideal bool" || s == "error" ||
- s == "untyped nil" || s == "unsafe.Pointer" {
- return false
- }
- return true
- }
- if !checkType(s.info.Types[v1]) || !checkType(s.info.Types[v2]) {
- return nil
- }
- var tv types.TypeAndValue
- if isConstExpr(s.info, v1) {
- flags |= SonarConst1
- } else {
- tv = s.info.Types[v1]
- }
- if isConstExpr(s.info, v2) {
- flags |= SonarConst2
- } else {
- tv = s.info.Types[v2]
- }
- if flags&SonarConst1 != 0 && flags&SonarConst2 != 0 {
- return nil
- }
- id := int(flags) | sonarSeq<<8
- startPos := s.fset.Position(nn.Pos())
- endPos := s.fset.Position(nn.End())
- *s.blocks = append(*s.blocks, CoverBlock{sonarSeq, s.fullName, startPos.Line, startPos.Column, endPos.Line, endPos.Column, int(flags)})
- sonarSeq++
- block := &ast.BlockStmt{}
-
- typstr := tv.Type.String()
- if strings.HasPrefix(typstr, s.pkg+".") {
- typstr = typstr[len(s.pkg)+1:]
- }
- if idx := strings.LastIndexByte(typstr, '/'); idx != -1 {
- typstr = typstr[idx+1:]
- }
- conv := func(name string, v ast.Expr) ast.Expr {
- // Convert const to the type of the other expr.
- isConst := isConstExpr(s.info, v)
- badConst := false
- if isConst {
- c := s.info.Types[v].Value
- switch c.Kind() {
- case constant.Int:
- if v, ok := constant.Int64Val(c); !ok || int64(int(v)) != v {
- // Such const can't be used outside of its current context,
- // because it will be converted to int and that will fail.
- badConst = true
- }
- case constant.Float:
- badConst = true
- }
- }
- if badConst || isWeirdShift(s.info, v) {
- v = &ast.CallExpr{
- Fun: ast.NewIdent(typstr),
- Args: []ast.Expr{v},
- }
- s.info.Types[v] = tv
- }
- if !isConst {
- // Assign to a temp to avoid double side-effects.
- tmp := ast.NewIdent(name)
- block.List = append(block.List, &ast.AssignStmt{Tok: token.DEFINE, Lhs: []ast.Expr{tmp}, Rhs: []ast.Expr{v}})
- v = tmp
- s.info.Types[v] = tv
- }
- return v
- }
- v1 = conv("__gofuzz_v1", v1)
- v2 = conv("__gofuzz_v2", v2)
-
- block.List = append(block.List,
- &ast.ExprStmt{
- X: &ast.CallExpr{
- Fun: &ast.SelectorExpr{X: ast.NewIdent(fuzzdepPkg), Sel: ast.NewIdent("Sonar")},
- Args: []ast.Expr{v1, v2, &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(id)}},
- },
- },
- &ast.ReturnStmt{Results: []ast.Expr{&ast.BinaryExpr{Op: nn.Op, X: v1, Y: v2, OpPos: nn.Pos()}}},
- )
- nn.X = &ast.CallExpr{
- Fun: &ast.FuncLit{
- Type: &ast.FuncType{Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("_go_fuzz_dep_.Bool")}}}},
- Body: block,
- },
- }
- nn.Y = &ast.BasicLit{Kind: token.INT, Value: "true"}
- nn.Op = token.EQL
- return nil
-}
-
-func isWeirdShift(info *types.Info, n ast.Expr) bool {
- w := &WeirdShiftWalker{info: info}
- ast.Walk(w, n)
- return w.found
-}
-
-type WeirdShiftWalker struct {
- info *types.Info
- found bool
-}
-
-func (w *WeirdShiftWalker) Visit(n ast.Node) ast.Visitor {
- if bin, ok := n.(*ast.BinaryExpr); ok && (bin.Op == token.SHL || bin.Op == token.SHR) && isConstExpr(w.info, bin.X) {
- w.found = true
- }
- return w
-}
-
-func isConstExpr(info *types.Info, n ast.Expr) bool {
- tv := info.Types[n]
- if tv.Type == nil && tv.Value == nil {
- panic(fmt.Sprintf("untyped expression: %#v", n))
- }
- return tv.Value != nil
-}
-
-func isCap(n ast.Expr) bool {
- if call, ok := n.(*ast.CallExpr); ok {
- if id, ok2 := call.Fun.(*ast.Ident); ok2 {
- return id.Name == "cap"
- }
- }
- return false
-}
-
-func isLen(n ast.Expr) bool {
- if call, ok := n.(*ast.CallExpr); ok {
- if id, ok2 := call.Fun.(*ast.Ident); ok2 {
- return id.Name == "len"
- }
- }
- return false
-}
-
-type LiteralCollector struct {
- ctxt *Context
- lits map[Literal]struct{}
-}
-
-func (lc *LiteralCollector) Visit(n ast.Node) (w ast.Visitor) {
- switch nn := n.(type) {
- default:
- return lc // recurse
- case *ast.ImportSpec:
- return nil
- case *ast.Field:
- return nil // ignore field tags
- case *ast.CallExpr:
- switch fn := nn.Fun.(type) {
- case *ast.Ident:
- if fn.Name == "panic" {
- return nil
- }
- case *ast.SelectorExpr:
- if id, ok := fn.X.(*ast.Ident); ok && (id.Name == "fmt" || id.Name == "errors") {
- return nil
- }
- }
- return lc
- case *ast.BasicLit:
- lit := nn.Value
- switch nn.Kind {
- case token.STRING:
- lc.lits[Literal{lc.unquote(lit), true}] = struct{}{}
- case token.CHAR:
- lc.lits[Literal{lc.unquote(lit), false}] = struct{}{}
- case token.INT:
- if lit[0] < '0' || lit[0] > '9' {
- lc.ctxt.failf("unsupported literal '%v'", lit)
- }
- v, err := strconv.ParseInt(lit, 0, 64)
- if err != nil {
- u, err := strconv.ParseUint(lit, 0, 64)
- if err != nil {
- lc.ctxt.failf("failed to parse int literal '%v': %v", lit, err)
- }
- v = int64(u)
- }
- var val []byte
- if v >= -(1<<7) && v < 1<<8 {
- val = append(val, byte(v))
- } else if v >= -(1<<15) && v < 1<<16 {
- val = append(val, byte(v), byte(v>>8))
- } else if v >= -(1<<31) && v < 1<<32 {
- val = append(val, byte(v), byte(v>>8), byte(v>>16), byte(v>>24))
- } else {
- val = append(val, byte(v), byte(v>>8), byte(v>>16), byte(v>>24), byte(v>>32), byte(v>>40), byte(v>>48), byte(v>>56))
- }
- lc.lits[Literal{string(val), false}] = struct{}{}
- }
- return nil
- }
-}
-
-func trimComments(file *ast.File, fset *token.FileSet) []*ast.CommentGroup {
- var comments []*ast.CommentGroup
- for _, group := range file.Comments {
- var list []*ast.Comment
- for _, comment := range group.List {
- if strings.HasPrefix(comment.Text, "//go:") && !strings.HasPrefix(comment.Text, "//go:build") && fset.Position(comment.Slash).Column == 1 {
- list = append(list, comment)
- }
- }
- if list != nil {
- comments = append(comments, &ast.CommentGroup{List: list})
- }
- }
- return comments
-}
-
-func initialComments(content []byte) []byte {
- // Derived from go/build.Context.shouldBuild.
- end := 0
- p := content
- for len(p) > 0 {
- line := p
- if i := bytes.IndexByte(line, '\n'); i >= 0 {
- line, p = line[:i], p[i+1:]
- } else {
- p = p[len(p):]
- }
- line = bytes.TrimSpace(line)
- if len(line) == 0 { // Blank line.
- end = len(content) - len(p)
- continue
- }
- if !bytes.HasPrefix(line, slashslash) { // Not comment line.
- break
- }
- }
- return content[:end]
-}
-
-type File struct {
- fset *token.FileSet
- pkg string
- fullName string
- astFile *ast.File
- blocks *[]CoverBlock
- info *types.Info
-}
-
-var slashslash = []byte("//")
-
-func (f *File) Visit(node ast.Node) ast.Visitor {
- switch n := node.(type) {
- case *ast.FuncDecl:
- if n.Name.String() == "init" {
- // Don't instrument init functions.
- // They run regardless of what we do, so it is just noise.
- return nil
- }
- case *ast.GenDecl:
- if n.Tok != token.VAR {
- return nil // constants and types are not interesting
- }
-
- case *ast.BlockStmt:
- // If it's a switch or select, the body is a list of case clauses; don't tag the block itself.
- if len(n.List) > 0 {
- switch n.List[0].(type) {
- case *ast.CaseClause: // switch
- for _, n := range n.List {
- clause := n.(*ast.CaseClause)
- clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
- }
- return f
- case *ast.CommClause: // select
- for _, n := range n.List {
- clause := n.(*ast.CommClause)
- clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
- }
- return f
- }
- }
- n.List = f.addCounters(n.Lbrace, n.Rbrace+1, n.List, true) // +1 to step past closing brace.
- case *ast.IfStmt:
- if n.Init != nil {
- ast.Walk(f, n.Init)
- }
- if n.Cond != nil {
- ast.Walk(f, n.Cond)
- }
- ast.Walk(f, n.Body)
- if n.Else == nil {
- // Add else because we want coverage for "not taken".
- n.Else = &ast.BlockStmt{
- Lbrace: n.Body.End(),
- Rbrace: n.Body.End(),
- }
- }
- // The elses are special, because if we have
- // if x {
- // } else if y {
- // }
- // we want to cover the "if y". To do this, we need a place to drop the counter,
- // so we add a hidden block:
- // if x {
- // } else {
- // if y {
- // }
- // }
- switch stmt := n.Else.(type) {
- case *ast.IfStmt:
- block := &ast.BlockStmt{
- Lbrace: n.Body.End(), // Start at end of the "if" block so the covered part looks like it starts at the "else".
- List: []ast.Stmt{stmt},
- Rbrace: stmt.End(),
- }
- n.Else = block
- case *ast.BlockStmt:
- stmt.Lbrace = n.Body.End() // Start at end of the "if" block so the covered part looks like it starts at the "else".
- default:
- panic("unexpected node type in if")
- }
- ast.Walk(f, n.Else)
- return nil
- case *ast.ForStmt:
- // TODO: handle increment statement
- case *ast.SelectStmt:
- // Don't annotate an empty select - creates a syntax error.
- if n.Body == nil || len(n.Body.List) == 0 {
- return nil
- }
- case *ast.SwitchStmt:
- hasDefault := false
- if n.Body == nil {
- n.Body = new(ast.BlockStmt)
- }
- for _, s := range n.Body.List {
- if cas, ok := s.(*ast.CaseClause); ok && cas.List == nil {
- hasDefault = true
- break
- }
- }
- if !hasDefault {
- // Add default case to get additional coverage.
- n.Body.List = append(n.Body.List, &ast.CaseClause{})
- }
-
- // Don't annotate an empty switch - creates a syntax error.
- if n.Body == nil || len(n.Body.List) == 0 {
- return nil
- }
- case *ast.TypeSwitchStmt:
- // Don't annotate an empty type switch - creates a syntax error.
- // TODO: add default case
- if n.Body == nil || len(n.Body.List) == 0 {
- return nil
- }
- case *ast.BinaryExpr:
- if n.Op == token.LAND || n.Op == token.LOR {
- // Replace:
- // x && y
- // with:
- // x && func() T { return y }
- // where T is a bool of the same type as n (and x and y).
-
- // Spelling T correctly is a little tricky.
- // go/types gives us a canonical name for T,
- // but we can't always use that canonical name in the code directly;
- // in the general case, it is of the form a/b/c/d.U.
- // When U is the built-in bool, or defined in the current package,
- // or defined in a dot-imported package, we want just U.
- // When U is in another package, we want d.U.
- // When U is in another package, imported under the name e, we want e.U.
- // (And when the built-in bool type is shadowed, we're just screwed.)
- // Handling all of these cases correctly is hard (it requires parsing the imports),
- // so we handle just the common cases.
-
- // types.Default maps untyped bools to typed bools.
- typ := types.Default(f.info.Types[n].Type).String()
- // If we're in the current package, strip the package path.
- if strings.HasPrefix(typ, f.pkg+".") {
- typ = typ[len(f.pkg)+1:]
- }
- // If we're still in a package, assume it was imported with a reasonable name.
- if i := strings.LastIndexByte(typ, '/'); i >= 0 {
- typ = typ[i+1:]
- }
-
- n.Y = &ast.CallExpr{
- Fun: &ast.FuncLit{
- Type: &ast.FuncType{Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent(typ)}}}},
- Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{n.Y}}}},
- },
- }
- }
- }
- return f
-}
-
-func (f *File) addImport(path, name, anyIdent string) {
- newImport := &ast.ImportSpec{
- Name: ast.NewIdent(name),
- Path: &ast.BasicLit{
- Kind: token.STRING,
- Value: fmt.Sprintf("%q", path),
- },
- }
- impDecl := &ast.GenDecl{
- Lparen: f.astFile.Name.End(),
- Tok: token.IMPORT,
- Specs: []ast.Spec{
- newImport,
- },
- Rparen: f.astFile.Name.End(),
- }
- // Make the new import the first Decl in the file.
- astFile := f.astFile
- astFile.Decls = append(astFile.Decls, nil)
- copy(astFile.Decls[1:], astFile.Decls[0:])
- astFile.Decls[0] = impDecl
- astFile.Imports = append(astFile.Imports, newImport)
-
- // Now refer to the package, just in case it ends up unused.
- // That is, append to the end of the file the declaration
- // var _ = _cover_atomic_.AddUint32
- reference := &ast.GenDecl{
- Tok: token.VAR,
- Specs: []ast.Spec{
- &ast.ValueSpec{
- Names: []*ast.Ident{
- ast.NewIdent("_"),
- },
- Values: []ast.Expr{
- &ast.SelectorExpr{
- X: ast.NewIdent(name),
- Sel: ast.NewIdent(anyIdent),
- },
- },
- },
- },
- }
- astFile.Decls = append(astFile.Decls, reference)
-}
-
-func (f *File) addCounters(pos, blockEnd token.Pos, list []ast.Stmt, extendToClosingBrace bool) []ast.Stmt {
- // Special case: make sure we add a counter to an empty block. Can't do this below
- // or we will add a counter to an empty statement list after, say, a return statement.
- if len(list) == 0 {
- return []ast.Stmt{f.newCounter(pos, blockEnd, 0)}
- }
- // We have a block (statement list), but it may have several basic blocks due to the
- // appearance of statements that affect the flow of control.
- var newList []ast.Stmt
- for {
- // Find first statement that affects flow of control (break, continue, if, etc.).
- // It will be the last statement of this basic block.
- var last int
- end := blockEnd
- for last = 0; last < len(list); last++ {
- end = f.statementBoundary(list[last])
- if f.endsBasicSourceBlock(list[last]) {
- extendToClosingBrace = false // Block is broken up now.
- last++
- break
- }
- }
- if extendToClosingBrace {
- end = blockEnd
- }
- if pos != end { // Can have no source to cover if e.g. blocks abut.
- newList = append(newList, f.newCounter(pos, end, last))
- }
- newList = append(newList, list[0:last]...)
- list = list[last:]
- if len(list) == 0 {
- break
- }
- pos = list[0].Pos()
- }
- return newList
-}
-
-func (f *File) endsBasicSourceBlock(s ast.Stmt) bool {
- switch s := s.(type) {
- case *ast.BlockStmt:
- // Treat blocks like basic blocks to avoid overlapping counters.
- return true
- case *ast.BranchStmt:
- return true
- case *ast.ForStmt:
- return true
- case *ast.IfStmt:
- return true
- case *ast.LabeledStmt:
- return f.endsBasicSourceBlock(s.Stmt)
- case *ast.RangeStmt:
- return true
- case *ast.SwitchStmt:
- return true
- case *ast.SelectStmt:
- return true
- case *ast.TypeSwitchStmt:
- return true
- case *ast.ExprStmt:
- // Calls to panic change the flow.
- // We really should verify that "panic" is the predefined function,
- // but without type checking we can't and the likelihood of it being
- // an actual problem is vanishingly small.
- if call, ok := s.X.(*ast.CallExpr); ok {
- if ident, ok := call.Fun.(*ast.Ident); ok && ident.Name == "panic" && len(call.Args) == 1 {
- return true
- }
- }
- }
- found, _ := hasFuncLiteral(s)
- return found
-}
-
-func (f *File) statementBoundary(s ast.Stmt) token.Pos {
- // Control flow statements are easy.
- switch s := s.(type) {
- case *ast.BlockStmt:
- // Treat blocks like basic blocks to avoid overlapping counters.
- return s.Lbrace
- case *ast.IfStmt:
- found, pos := hasFuncLiteral(s.Init)
- if found {
- return pos
- }
- found, pos = hasFuncLiteral(s.Cond)
- if found {
- return pos
- }
- return s.Body.Lbrace
- case *ast.ForStmt:
- found, pos := hasFuncLiteral(s.Init)
- if found {
- return pos
- }
- found, pos = hasFuncLiteral(s.Cond)
- if found {
- return pos
- }
- found, pos = hasFuncLiteral(s.Post)
- if found {
- return pos
- }
- return s.Body.Lbrace
- case *ast.LabeledStmt:
- return f.statementBoundary(s.Stmt)
- case *ast.RangeStmt:
- found, pos := hasFuncLiteral(s.X)
- if found {
- return pos
- }
- return s.Body.Lbrace
- case *ast.SwitchStmt:
- found, pos := hasFuncLiteral(s.Init)
- if found {
- return pos
- }
- found, pos = hasFuncLiteral(s.Tag)
- if found {
- return pos
- }
- return s.Body.Lbrace
- case *ast.SelectStmt:
- return s.Body.Lbrace
- case *ast.TypeSwitchStmt:
- found, pos := hasFuncLiteral(s.Init)
- if found {
- return pos
- }
- return s.Body.Lbrace
- }
- found, pos := hasFuncLiteral(s)
- if found {
- return pos
- }
- return s.End()
-}
-
-var counterGen uint32
-
-func genCounter() int {
- counterGen++
- id := counterGen
- buf := []byte{byte(id), byte(id >> 8), byte(id >> 16), byte(id >> 24)}
- hash := sha1.Sum(buf)
- return int(uint16(hash[0]) | uint16(hash[1])<<8)
-}
-
-func (f *File) newCounter(start, end token.Pos, numStmt int) ast.Stmt {
- cnt := genCounter()
-
- if f.blocks != nil {
- s := f.fset.Position(start)
- e := f.fset.Position(end)
- *f.blocks = append(*f.blocks, CoverBlock{cnt, f.fullName, s.Line, s.Column, e.Line, e.Column, numStmt})
- }
-
- idx := &ast.BasicLit{
- Kind: token.INT,
- Value: strconv.Itoa(cnt),
- }
- counter := &ast.IndexExpr{
- X: &ast.SelectorExpr{
- X: ast.NewIdent(fuzzdepPkg),
- Sel: ast.NewIdent("CoverTab"),
- },
- Index: idx,
- }
- return &ast.IncDecStmt{
- X: counter,
- Tok: token.INC,
- }
-}
-
-func (f *File) print(w io.Writer) {
- cfg := printer.Config{
- Mode: printer.SourcePos,
- Tabwidth: 8,
- Indent: 0,
- }
- cfg.Fprint(w, f.fset, f.astFile)
-}
-
-type funcLitFinder token.Pos
-
-func (f *funcLitFinder) Visit(node ast.Node) (w ast.Visitor) {
- if f.found() {
- return nil // Prune search.
- }
- switch n := node.(type) {
- case *ast.FuncLit:
- *f = funcLitFinder(n.Body.Lbrace)
- return nil // Prune search.
- }
- return f
-}
-
-func (f *funcLitFinder) found() bool {
- return token.Pos(*f) != token.NoPos
-}
-
-func hasFuncLiteral(n ast.Node) (bool, token.Pos) {
- if n == nil {
- return false, 0
- }
- var literal funcLitFinder
- ast.Walk(&literal, n)
- return literal.found(), token.Pos(literal)
-}
-
-func (lc *LiteralCollector) unquote(s string) string {
- t, err := strconv.Unquote(s)
- if err != nil {
- lc.ctxt.failf("cover: improperly quoted string %q\n", s)
- }
- return t
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/main.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/main.go
deleted file mode 100644
index 91305ee37..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-build/main.go
+++ /dev/null
@@ -1,904 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package main
-
-import (
- "archive/zip"
- "bytes"
- "encoding/json"
- "flag"
- "fmt"
- "go/ast"
- "go/parser"
- "go/token"
- "go/types"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "runtime/pprof"
- "strings"
- "text/template"
- "unicode"
- "unicode/utf8"
-
- "golang.org/x/tools/go/packages"
-
- . "github.com/dvyukov/go-fuzz/internal/go-fuzz-types"
-)
-
-var (
- flagTag = flag.String("tags", "", "a space-separated list of build tags to consider satisfied during the build")
- flagOut = flag.String("o", "", "output file")
- flagFunc = flag.String("func", "", "preferred entry function")
- flagWork = flag.Bool("work", false, "don't remove working directory")
- flagRace = flag.Bool("race", false, "enable race detector")
- flagCPU = flag.Bool("cpuprofile", false, "generate cpu profile in cpu.pprof")
- flagLibFuzzer = flag.Bool("libfuzzer", false, "output static archive for use with libFuzzer")
- flagBuildX = flag.Bool("x", false, "print the commands if build fails")
- flagPreserve = flag.String("preserve", "", "a comma-separated list of import paths not to instrument")
- flagGoCmd = flag.String("go", "go", `path to "go" command`)
-)
-
-func makeTags() string {
- tags := "gofuzz"
- if *flagLibFuzzer {
- tags += " gofuzz_libfuzzer"
- }
- if *flagRace {
- tags += " race"
- }
- if len(*flagTag) > 0 {
- tags += " " + *flagTag
- }
- return tags
-}
-
-// basePackagesConfig returns a base golang.org/x/tools/go/packages.Config
-// that clients can then modify and use for calls to go/packages.
-func basePackagesConfig() *packages.Config {
- cfg := new(packages.Config)
-
- // Note that we do not set GO111MODULE here in order to respect any GO111MODULE
- // setting by the user as we are finding dependencies. Note, however, that
- // we are still setting up a GOPATH to build, so we later will force
- // GO111MODULE to be off when building so that we are in GOPATH mode.
- // If the user has not set GO111MODULE, the meaning here is
- // left up to cmd/go (defaulting to 'auto' in Go 1.11-1.13,
- // but likely defaulting to 'on' at some point during Go 1.14
- // development cycle).
- // Also note that we are leaving the overall cfg structure
- // in place to support future experimentation, etc.
- cfg.Env = os.Environ()
- return cfg
-}
-
-// checkModVendor reports if the GOFLAGS env variable
-// contains -mod=vendor, which enables vendoring for modules.
-func checkModVendor() bool {
- val := os.Getenv("GOFLAGS")
- for _, s := range strings.Split(val, " ") {
- if s == "-mod=vendor" {
- return true
- }
- }
- return false
-}
-
-// main copies the package with all dependent packages into a temp dir,
-// instruments Go source files there, and builds setting GOROOT to the temp dir.
-func main() {
- flag.Parse()
- c := new(Context)
-
- if flag.NArg() > 1 {
- c.failf("usage: go-fuzz-build [pkg]")
- }
-
- pkg := "."
- if flag.NArg() == 1 {
- pkg = flag.Arg(0)
- }
- if *flagFunc != "" && !isFuzzFuncName(*flagFunc) {
- c.failf("provided -func=%v, but %v is not a fuzz function name", *flagFunc, *flagFunc)
- }
- if *flagLibFuzzer && *flagRace {
- c.failf("-race and -libfuzzer are incompatible")
- }
- if checkModVendor() {
- // We don't support -mod=vendor with modules.
- // Part of the issue is go-fuzz-dep and go-fuzz-defs
- // won't be in the user's vendor directory.
- c.failf("GOFLAGS with -mod=vendor is not supported")
- }
-
- c.startProfiling() // start pprof as requested
- c.loadPkg(pkg) // load and typecheck pkg
- c.getEnv() // discover GOROOT, GOPATH
- c.loadStd() // load standard library
- c.calcIgnore() // calculate set of packages to ignore
- c.makeWorkdir() // create workdir
- defer c.cleanup() // delete workdir as needed, etc.
- c.populateWorkdir() // copy tools and packages to workdir as needed
-
- if *flagOut == "" {
- ext := ".zip"
- if *flagLibFuzzer {
- ext = ".a"
- }
- *flagOut = c.pkgs[0].Name + "-fuzz" + ext
- }
-
- // Gather literals, instrument, and compile.
- // Order matters here!
- // buildInstrumentedBinary (and instrumentPackages) modify the AST.
- // (We don't want to re-parse and re-typecheck every time, for performance.)
- // So we gather literals first, while the AST is pristine.
- // Then we add coverage and build.
- // Then we add sonar and build.
- // TODO: migrate to use cmd/internal/edit instead of AST modification.
- // This has several benefits: (1) It is easier to work with.
- // (2) 'go cover' has switched to it; we would get the benefit of
- // upstream bug fixes, of which there has been at least one (around gotos and labels).
- // (3) It leaves the AST intact, so we are less order-sensitive.
- // The primary blocker is that we want good line numbers for when we find crashers.
- // go/printer handles this automatically using Mode printer.SourcePos.
- // We'd need to implement that support ourselves. (It's do-able but non-trivial.)
- // See also https://golang.org/issue/29824.
- lits := c.gatherLiterals()
- var blocks, sonar []CoverBlock
-
- if *flagLibFuzzer {
- archive := c.buildInstrumentedBinary(&blocks, nil)
- c.moveFile(archive, *flagOut)
- return
- }
-
- coverBin := c.buildInstrumentedBinary(&blocks, nil)
- sonarBin := c.buildInstrumentedBinary(nil, &sonar)
- metaData := c.createMeta(lits, blocks, sonar)
- defer func() {
- os.Remove(coverBin)
- os.Remove(sonarBin)
- os.Remove(metaData)
- }()
-
- outf, err := os.Create(*flagOut)
- if err != nil {
- c.failf("failed to create output file: %v", err)
- }
- zipw := zip.NewWriter(outf)
- zipFile := func(name, datafile string) {
- w, err := zipw.Create(name)
- if err != nil {
- c.failf("failed to create zip file: %v", err)
- }
- f, err := os.Open(datafile)
- if err != nil {
- c.failf("failed to open data file %v", datafile)
- }
- if _, err := io.Copy(w, f); err != nil {
- c.failf("failed to write %v to zip file: %v", datafile, err)
- }
- // best effort: close and remove our temp file
- f.Close()
- os.Remove(datafile)
- }
- zipFile("cover.exe", coverBin)
- zipFile("sonar.exe", sonarBin)
- zipFile("metadata", metaData)
- if err := zipw.Close(); err != nil {
- c.failf("failed to close zip file: %v", err)
- }
- if err := outf.Close(); err != nil {
- c.failf("failed to close out file: %v", err)
- }
-}
-
-// Context holds state for a go-fuzz-build run.
-type Context struct {
- fuzzpkg *packages.Package // package containing Fuzz function
- pkgs []*packages.Package // typechecked root packages
-
- std map[string]bool // set of packages in the standard library
- ignore map[string]bool // set of packages to ignore during instrumentation
-
- allFuncs []string // all fuzz functions found in package
-
- workdir string
- GOROOT string
- GOPATH string
-
- cpuprofile *os.File
-
- cmdGoHasTrimPath bool // does the active version of cmd/go have the -trimpath flag?
-}
-
-// getEnv determines GOROOT and GOPATH and updates c accordingly.
-func (c *Context) getEnv() {
- env := map[string]string{
- "GOROOT": "",
- "GOPATH": "",
- }
- for k := range env {
- v := os.Getenv(k)
- if v != "" {
- env[k] = v
- continue
- }
- // TODO: make a single call ("go env GOROOT GOPATH") instead
- out, err := exec.Command(*flagGoCmd, "env", k).CombinedOutput()
- if err != nil || len(out) == 0 {
- c.failf("%s is not set and failed to locate it: 'go env %s' returned '%s' (%v)", k, k, out, err)
- }
- env[k] = strings.TrimSpace(string(out))
- }
- c.GOROOT = env["GOROOT"]
- c.GOPATH = env["GOPATH"]
-
- out, err := exec.Command(*flagGoCmd, "list", "-f", "'{{context.ReleaseTags}}'", "runtime").CombinedOutput()
- if err != nil || len(out) == 0 {
- c.failf("go list -f '{{context.ReleaseTags}}' runtime returned '%s' (%v)", out, err)
- }
- c.cmdGoHasTrimPath = bytes.Contains(out, []byte("go1.13"))
-}
-
-// startProfiling starts pprof profiling, if requested.
-func (c *Context) startProfiling() {
- if !*flagCPU {
- return
- }
- var err error
- c.cpuprofile, err = os.Create("cpu.pprof")
- if err != nil {
- c.failf("could not create cpu profile: %v", err)
- }
- pprof.StartCPUProfile(c.cpuprofile)
-}
-
-// loadPkg loads, parses, and typechecks pkg (the package containing the Fuzz function),
-// go-fuzz-dep, and their dependencies.
-func (c *Context) loadPkg(pkg string) {
- // Resolve pkg.
- // See https://golang.org/issue/30826 and https://golang.org/issue/30828.
- rescfg := basePackagesConfig()
- rescfg.Mode = packages.NeedName
- rescfg.BuildFlags = []string{"-tags", makeTags()}
- respkgs, err := packages.Load(rescfg, pkg)
- if err != nil {
- c.failf("could not resolve package %q: %v", pkg, err)
- }
- if len(respkgs) != 1 {
- paths := make([]string, len(respkgs))
- for i, p := range respkgs {
- paths[i] = p.PkgPath
- }
- c.failf("cannot build multiple packages, but %q resolved to: %v", pkg, strings.Join(paths, ", "))
- }
- if respkgs[0].Name == "main" {
- c.failf("cannot fuzz package main")
- }
- pkgpath := respkgs[0].PkgPath
-
- // Load, parse, and type-check all packages.
- // We'll use the type information later.
- // This also provides better error messages in the case
- // of invalid code than trying to compile instrumented code.
- cfg := basePackagesConfig()
- cfg.Mode = packages.LoadAllSyntax
- cfg.BuildFlags = []string{"-tags", makeTags()}
- // use custom ParseFile in order to get comments
- cfg.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
- return parser.ParseFile(fset, filename, src, parser.ParseComments)
- }
- // We need to load:
- // * the target package, obviously
- // * go-fuzz-dep, since we use it for instrumentation
- // * reflect, if we are using libfuzzer, since its generated main function requires it
- loadpkgs := []string{pkg, "github.com/dvyukov/go-fuzz/go-fuzz-dep"}
- if *flagLibFuzzer {
- loadpkgs = append(loadpkgs, "reflect")
- }
- initial, err := packages.Load(cfg, loadpkgs...)
- if err != nil {
- c.failf("could not load packages: %v", err)
- }
-
- // Stop if any package had errors.
- if packages.PrintErrors(initial) > 0 {
- c.failf("typechecking of %v failed", pkg)
- }
-
- c.pkgs = initial
-
- // Find the fuzz package among c.pkgs.
- for _, p := range initial {
- if p.PkgPath == pkgpath {
- c.fuzzpkg = p
- break
- }
- }
- if c.fuzzpkg == nil {
- c.failf("internal error: failed to find fuzz package; please file an issue")
- }
-
- // Find all fuzz functions in fuzzpkg.
- foundFlagFunc := false
- s := c.fuzzpkg.Types.Scope()
- for _, n := range s.Names() {
- if !isFuzzFuncName(n) {
- continue
- }
- // Check that n is a function with an appropriate signature.
- typ := s.Lookup(n).Type()
- sig, ok := typ.(*types.Signature)
- if !ok || sig.Variadic() || !isFuzzSig(sig) {
- if n == *flagFunc {
- c.failf("provided -func=%v, but %v is not a fuzz function", *flagFunc, *flagFunc)
- }
- continue
- }
- // n is a fuzz function.
- c.allFuncs = append(c.allFuncs, n)
- foundFlagFunc = foundFlagFunc || n == *flagFunc
- }
-
- if len(c.allFuncs) == 0 {
- c.failf("could not find any fuzz functions in %v", c.fuzzpkg.PkgPath)
- }
- if len(c.allFuncs) > 255 {
- c.failf("go-fuzz-build supports a maximum of 255 fuzz functions, found %v; please file an issue", len(c.allFuncs))
- }
-
- if *flagFunc != "" {
- // Specific fuzz function requested.
- // If the requested function doesn't exist, fail.
- if !foundFlagFunc {
- c.failf("could not find fuzz function %v in %v", *flagFunc, c.fuzzpkg.PkgPath)
- }
- } else {
- // No specific fuzz function requested.
- // If there's only one fuzz function, mark it as preferred.
- // If there's more than one...
- // ...for go-fuzz, that's fine; one can be specified later on the command line.
- // ...for libfuzzer, that's not fine, as there is no way to specify one later.
- if len(c.allFuncs) == 1 {
- *flagFunc = c.allFuncs[0]
- } else if *flagLibFuzzer {
- c.failf("must specify a fuzz function with -libfuzzer, found: %v", strings.Join(c.allFuncs, ", "))
- }
- }
-}
-
-// isFuzzSig reports whether sig is of the form
-// func FuzzFunc(data []byte) int
-func isFuzzSig(sig *types.Signature) bool {
- return tupleHasTypes(sig.Params(), "[]byte") && tupleHasTypes(sig.Results(), "int")
-}
-
-// tupleHasTypes reports whether tuple is composed of
-// elements with exactly the types in types.
-func tupleHasTypes(tuple *types.Tuple, types ...string) bool {
- if tuple.Len() != len(types) {
- return false
- }
- for i, t := range types {
- if tuple.At(i).Type().String() != t {
- return false
- }
- }
- return true
-}
-
-func isFuzzFuncName(name string) bool {
- return isTest(name, "Fuzz")
-}
-
-// isTest is copied verbatim, along with its name,
-// from GOROOT/src/cmd/go/internal/load/test.go.
-// isTest tells whether name looks like a test (or benchmark, according to prefix).
-// It is a Test (say) if there is a character after Test that is not a lower-case letter.
-// We don't want TesticularCancer.
-func isTest(name, prefix string) bool {
- if !strings.HasPrefix(name, prefix) {
- return false
- }
- if len(name) == len(prefix) { // "Test" is ok
- return true
- }
- rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
- return !unicode.IsLower(rune)
-}
-
-// loadStd finds the set of standard library package paths.
-func (c *Context) loadStd() {
- // Find out what packages are in the standard library.
- cfg := basePackagesConfig()
- cfg.Mode = packages.NeedName
- stdpkgs, err := packages.Load(cfg, "std")
- if err != nil {
- c.failf("could not load standard library: %v", err)
- }
- c.std = make(map[string]bool, len(stdpkgs))
- for _, p := range stdpkgs {
- c.std[p.PkgPath] = true
- }
-}
-
-// makeWorkdir creates the workdir, logging as requested.
-func (c *Context) makeWorkdir() {
- // TODO: make workdir stable, so that we can use cmd/go's build cache?
- // See https://github.com/golang/go/issues/29430.
- var err error
- c.workdir, err = ioutil.TempDir("", "go-fuzz-build")
- if err != nil {
- c.failf("failed to create temp dir: %v", err)
- }
- if *flagWork {
- fmt.Printf("workdir: %v\n", c.workdir)
- }
-}
-
-// cleanup ensures a clean exit. It should be called on all (controllable) exit paths.
-func (c *Context) cleanup() {
- if !*flagWork && c.workdir != "" {
- os.RemoveAll(c.workdir)
- }
- if c.cpuprofile != nil {
- pprof.StopCPUProfile()
- c.cpuprofile.Close()
- }
-}
-
-// populateWorkdir prepares workdir for builds.
-func (c *Context) populateWorkdir() {
- // TODO: instead of reconstructing the world,
- // can we use a bunch of replace directives in a go.mod?
-
- // TODO: make all this I/O concurrent (up to a limit).
- // It's a non-trivial part of build time.
- // Question: Do it here or in copyDir?
-
- // TODO: See if we can avoid making toolchain copies,
- // using some combination of env vars and toolexec.
- if *flagLibFuzzer || *flagRace {
- c.copyDir(filepath.Join(c.GOROOT, "src", "runtime", "cgo"), filepath.Join(c.workdir, "goroot", "src", "runtime", "cgo"))
- }
- if *flagRace {
- c.copyDir(filepath.Join(c.GOROOT, "src", "runtime", "race"), filepath.Join(c.workdir, "goroot", "src", "runtime", "race"))
- c.copyDir(filepath.Join(c.GOROOT, "src", "sync", "atomic"), filepath.Join(c.workdir, "goroot", "src", "sync", "atomic"))
- }
- c.copyDir(filepath.Join(c.GOROOT, "pkg", "tool"), filepath.Join(c.workdir, "goroot", "pkg", "tool"))
- if _, err := os.Stat(filepath.Join(c.GOROOT, "pkg", "include")); err == nil {
- c.copyDir(filepath.Join(c.GOROOT, "pkg", "include"), filepath.Join(c.workdir, "goroot", "pkg", "include"))
- } else {
- // Cross-compilation is not implemented.
- c.copyDir(filepath.Join(c.GOROOT, "pkg", runtime.GOOS+"_"+runtime.GOARCH), filepath.Join(c.workdir, "goroot", "pkg", runtime.GOOS+"_"+runtime.GOARCH))
- }
- // go1.17 added abi_amd64.h
- if _, err := os.Stat(filepath.Join(c.GOROOT, "src", "runtime", "cgo", "abi_amd64.h")); err == nil {
- c.mkdirAll(filepath.Join(c.workdir, "goroot", "src", "runtime", "cgo"))
- c.copyFile(filepath.Join(c.GOROOT, "src", "runtime", "cgo", "abi_amd64.h"), filepath.Join(c.workdir, "goroot", "src", "runtime", "cgo", "abi_amd64.h"))
- }
-
- // Clone our package, go-fuzz-deps, and all dependencies.
- // TODO: we might not need to do this for all packages.
- // We know that we'll be writing out instrumented Go code later;
- // we could instead just os.MkdirAll and copy non-Go files here.
- // We'd still need to do a full package clone for packages that
- // we aren't instrumenting (c.ignore).
- packages.Visit(c.pkgs, nil, func(p *packages.Package) {
- c.clonePackage(p)
- })
- c.copyFuzzDep()
-}
-
-func (c *Context) createMeta(lits map[Literal]struct{}, blocks []CoverBlock, sonar []CoverBlock) string {
- meta := MetaData{Blocks: blocks, Sonar: sonar, Funcs: c.allFuncs, DefaultFunc: *flagFunc}
- for k := range lits {
- meta.Literals = append(meta.Literals, k)
- }
- data, err := json.Marshal(meta)
- if err != nil {
- c.failf("failed to serialize meta information: %v", err)
- }
- f := c.tempFile()
- c.writeFile(f, data)
- return f
-}
-
-func (c *Context) buildInstrumentedBinary(blocks *[]CoverBlock, sonar *[]CoverBlock) string {
- c.instrumentPackages(blocks, sonar)
- mainPkg := c.createFuzzMain()
- outf := c.tempFile()
- args := []string{"build", "-tags", makeTags()}
- if *flagBuildX {
- args = append(args, "-x")
-
- if *flagWork {
- args = append(args, "-work")
- }
- }
- if *flagRace {
- args = append(args, "-race")
- }
- if *flagLibFuzzer {
- args = append(args, "-buildmode=c-archive")
- }
- if c.cmdGoHasTrimPath {
- args = append(args, "-trimpath")
- }
- args = append(args, "-o", outf, mainPkg)
- cmd := exec.Command(*flagGoCmd, args...)
-
- // We are constructing a GOPATH environment, so while building
- // we force GOPATH mode here via GO111MODULE=off.
- cmd.Env = append(os.Environ(),
- "GOROOT="+filepath.Join(c.workdir, "goroot"),
- "GOPATH="+filepath.Join(c.workdir, "gopath"),
- "GO111MODULE=off",
- )
- if out, err := cmd.CombinedOutput(); err != nil {
- c.failf("failed to execute go build: %v\n%v", err, string(out))
- }
- return outf
-}
-
-func (c *Context) calcIgnore() {
- // No reason to instrument these.
- c.ignore = map[string]bool{
- "runtime/cgo": true,
- "runtime/pprof": true,
- "runtime/race": true,
- }
-
- // Roots: must not instrument these, nor any of their dependencies, to avoid import cycles.
- // Fortunately, these are mostly packages that are non-deterministic,
- // noisy (because they are low level), and/or not interesting.
- // We could manually maintain this list, but that makes go-fuzz-build
- // fragile in the face of internal standard library package changes.
- roots := c.packagesNamed("runtime", "github.com/dvyukov/go-fuzz/go-fuzz-dep")
- packages.Visit(roots, func(p *packages.Package) bool {
- c.ignore[p.PkgPath] = true
- return true
- }, nil)
-
- // Ignore any packages requested explicitly by the user.
- paths := strings.Split(*flagPreserve, ",")
- for _, path := range paths {
- c.ignore[path] = true
- }
-}
-
-func (c *Context) gatherLiterals() map[Literal]struct{} {
- nolits := map[string]bool{
- "math": true,
- "os": true,
- "unicode": true,
- }
-
- lits := make(map[Literal]struct{})
- visit := func(pkg *packages.Package) {
- if c.ignore[pkg.PkgPath] || nolits[pkg.PkgPath] {
- return
- }
- for _, f := range pkg.Syntax {
- ast.Walk(&LiteralCollector{lits: lits, ctxt: c}, f)
- }
- }
-
- packages.Visit(c.pkgs, nil, visit)
- return lits
-}
-
-func (c *Context) copyFuzzDep() {
- // Standard library packages can't depend on non-standard ones.
- // So we pretend that go-fuzz-dep is a standard one.
- // go-fuzz-dep depends on go-fuzz-defs, which creates a problem.
- // Fortunately (and intentionally), go-fuzz-defs contains only constants,
- // which can be duplicated safely.
- // So we eliminate the import statement and copy go-fuzz-defs/defs.go
- // directly into the go-fuzz-dep package.
- newDir := filepath.Join(c.workdir, "goroot", "src", "go-fuzz-dep")
- c.mkdirAll(newDir)
- dep := c.packageNamed("github.com/dvyukov/go-fuzz/go-fuzz-dep")
- for _, f := range dep.GoFiles {
- data := c.readFile(f)
- // Eliminate the dot import.
- data = bytes.Replace(data, []byte(`. "github.com/dvyukov/go-fuzz/go-fuzz-defs"`), nil, -1)
- c.writeFile(filepath.Join(newDir, filepath.Base(f)), data)
- }
-
- defs := c.packageNamed("github.com/dvyukov/go-fuzz/go-fuzz-defs")
- for _, f := range defs.GoFiles {
- data := c.readFile(f)
- // Adjust package name to match go-fuzz-deps.
- data = bytes.Replace(data, []byte("\npackage base"), []byte("\npackage gofuzzdep"), -1)
- c.writeFile(filepath.Join(newDir, "defs.go"), data)
- }
-}
-
-func (c *Context) funcMain() []byte {
- t := mainSrc
- if *flagLibFuzzer {
- t = mainSrcLibFuzzer
- }
- dot := map[string]interface{}{"Pkg": c.fuzzpkg.PkgPath, "AllFuncs": c.allFuncs, "DefaultFunc": *flagFunc}
- buf := new(bytes.Buffer)
- if err := t.Execute(buf, dot); err != nil {
- c.failf("could not execute template: %v", err)
- }
- return buf.Bytes()
-}
-
-func (c *Context) createFuzzMain() string {
- mainPkg := filepath.Join(c.fuzzpkg.PkgPath, "go.fuzz.main")
- path := filepath.Join(c.workdir, "gopath", "src", mainPkg)
- c.mkdirAll(path)
- c.writeFile(filepath.Join(path, "main.go"), c.funcMain())
- return mainPkg
-}
-
-func (c *Context) clonePackage(p *packages.Package) {
- root := "goroot"
- if !c.std[p.PkgPath] {
- root = "gopath"
- }
- newDir := filepath.Join(c.workdir, root, "src", p.PkgPath)
- c.mkdirAll(newDir)
-
- // examine "go:embed" directives, collect embedded filenames, use later
- for i, fullName := range p.CompiledGoFiles {
- if strings.HasSuffix(fullName, ".go") {
- for _, commentGroup := range trimComments(p.Syntax[i], p.Fset) {
- for _, comment := range commentGroup.List {
- if strings.HasPrefix(comment.Text, "//go:embed") {
- filename := comment.Text[len("//go:embed "):]
- dirname := filepath.Dir(fullName)
- fullname := fmt.Sprintf("%s/%s", dirname, filename)
- p.OtherFiles = append(p.OtherFiles, fullname)
- }
- }
- }
- }
- }
-
- if p.PkgPath == "unsafe" {
- // Write a dummy file. go/packages explicitly returns an empty GoFiles for it,
- // for reasons that are unclear, but cmd/go wants there to be a Go file in the package.
- c.writeFile(filepath.Join(newDir, "unsafe.go"), []byte(`package unsafe`))
- return
- }
-
- // Copy all the source code.
-
- // Use GoFiles instead of CompiledGoFiles here.
- // If we use CompiledGoFiles, we end up with code that cmd/go won't compile.
- // See https://golang.org/issue/30479 and Context.instrumentPackages.
- for _, f := range p.GoFiles {
- dst := filepath.Join(newDir, filepath.Base(f))
- c.copyFile(f, dst)
- }
- for _, f := range p.OtherFiles {
- dst := filepath.Join(newDir, filepath.Base(f))
- c.copyFile(f, dst)
- }
-
- // TODO: do we need to look for and copy go.mod?
-}
-
-// packageNamed extracts the package listed in path.
-func (c *Context) packageNamed(path string) (pkgs *packages.Package) {
- all := c.packagesNamed(path)
- if len(all) != 1 {
- c.failf("got multiple packages, requested only %v", path)
- }
- return all[0]
-}
-
-// packagesNamed extracts the packages listed in paths.
-func (c *Context) packagesNamed(paths ...string) (pkgs []*packages.Package) {
- pre := func(p *packages.Package) bool {
- for _, path := range paths {
- if p.PkgPath == path {
- pkgs = append(pkgs, p)
- break
- }
- }
- return len(pkgs) < len(paths) // continue only if we have not succeeded yet
- }
- packages.Visit(c.pkgs, pre, nil)
- return pkgs
-}
-
-func (c *Context) instrumentPackages(blocks *[]CoverBlock, sonar *[]CoverBlock) {
- visit := func(pkg *packages.Package) {
- if c.ignore[pkg.PkgPath] {
- return
- }
-
- root := "goroot"
- if !c.std[pkg.PkgPath] {
- root = "gopath"
- }
- path := filepath.Join(c.workdir, root, "src", pkg.PkgPath) // TODO: need filepath.FromSlash for pkg.PkgPath?
-
- for i, fullName := range pkg.CompiledGoFiles {
- fname := filepath.Base(fullName)
- if !strings.HasSuffix(fname, ".go") {
- // This is a cgo-generated file.
- // Instrumenting it currently does not work.
- // We copied the original Go file as part of copyPackageRewrite,
- // so we can just skip this one.
- // See https://golang.org/issue/30479.
- continue
- }
- f := pkg.Syntax[i]
-
- // TODO: rename trimComments?
- f.Comments = trimComments(f, pkg.Fset)
-
- buf := new(bytes.Buffer)
- content := c.readFile(fullName)
- buf.Write(initialComments(content)) // Retain '// +build' directives.
- instrument(pkg.PkgPath, fullName, pkg.Fset, f, pkg.TypesInfo, buf, blocks, sonar)
- tmp := c.tempFile()
- c.writeFile(tmp, buf.Bytes())
- outpath := filepath.Join(path, fname)
- if runtime.GOOS == "windows" {
- os.Remove(outpath)
- }
- c.moveFile(tmp, outpath)
- }
- }
-
- packages.Visit(c.pkgs, nil, visit)
-}
-
-func (c *Context) copyDir(dir, newDir string) {
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- c.failf("failed to scan dir '%v': %v", dir, err)
- }
- c.mkdirAll(newDir)
- for _, f := range files {
- src := filepath.Join(dir, f.Name())
- dst := filepath.Join(newDir, f.Name())
- if f.IsDir() {
- c.copyDir(src, dst)
- } else {
- c.copyFile(src, dst)
- }
- }
-}
-
-func (c *Context) copyFile(src, dst string) {
- r, err := os.Open(src)
- if err != nil {
- c.failf("copyFile: could not read %v", src, err)
- }
- w, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
- if err != nil {
- c.failf("copyFile: could not write %v: %v", dst, err)
- }
- if _, err := io.Copy(w, r); err != nil {
- c.failf("copyFile: copying failed: %v", err)
- }
- if err := r.Close(); err != nil {
- c.failf("copyFile: closing %v failed: %v", src, err)
- }
- if err := w.Close(); err != nil {
- c.failf("copyFile: closing %v failed: %v", dst, err)
- }
-}
-
-func (c *Context) moveFile(src, dst string) {
- c.copyFile(src, dst)
- err := os.Remove(src)
- if err != nil {
- c.failf("moveFile: removing %q failed: %v", src, err)
- }
-}
-
-func (c *Context) failf(str string, args ...interface{}) {
- c.cleanup()
- fmt.Fprintf(os.Stderr, str+"\n", args...)
- os.Exit(1)
-}
-
-// tempFile creates and deletes a temp file, and returns its path.
-// This is helpful when you need a temp path for an output file
-// that will be created by an external tool (go build) or by a call to writeFile.
-func (c *Context) tempFile() string {
- outf, err := ioutil.TempFile("", "go-fuzz")
- if err != nil {
- c.failf("failed to create temp file: %v", err)
- }
- outf.Close()
- os.Remove(outf.Name()) // necessary on Windows
- return outf.Name()
-}
-
-func (c *Context) readFile(name string) []byte {
- data, err := ioutil.ReadFile(name)
- if err != nil {
- c.failf("failed to read temp file: %v", err)
- }
- return data
-}
-
-func (c *Context) writeFile(name string, data []byte) {
- if err := ioutil.WriteFile(name, data, 0700); err != nil {
- c.failf("failed to write temp file: %v", err)
- }
-}
-
-func (c *Context) mkdirAll(dir string) {
- if err := os.MkdirAll(dir, 0700); err != nil {
- c.failf("failed to create temp dir: %v", err)
- }
-}
-
-var mainSrc = template.Must(template.New("main").Parse(`
-package main
-
-import (
- target "{{.Pkg}}"
- dep "go-fuzz-dep"
-)
-
-func main() {
- fns := []func([]byte)int {
- {{range .AllFuncs}}
- target.{{.}},
- {{end}}
- }
- dep.Main(fns)
-}
-`))
-
-var mainSrcLibFuzzer = template.Must(template.New("main").Parse(`
-package main
-
-import (
- "unsafe"
- "reflect"
- target "{{.Pkg}}"
- dep "go-fuzz-dep"
-)
-
-// #cgo CFLAGS: -Wall -Werror
-// #ifdef __linux__
-// __attribute__((weak, section("__libfuzzer_extra_counters")))
-// #else
-// #error Currently only Linux is supported
-// #endif
-// unsigned char GoFuzzCoverageCounters[65536];
-import "C"
-
-//export LLVMFuzzerInitialize
-func LLVMFuzzerInitialize(argc uintptr, argv uintptr) int {
- dep.Initialize(unsafe.Pointer(&C.GoFuzzCoverageCounters[0]), 65536)
- return 0
-}
-
-//export LLVMFuzzerTestOneInput
-func LLVMFuzzerTestOneInput(data uintptr, size uint64) int {
- sh := &reflect.SliceHeader{
- Data: data,
- Len: int(size),
- Cap: int(size),
- }
-
- input := *(*[]byte)(unsafe.Pointer(sh))
- target.{{.DefaultFunc}}(input)
-
- return 0
-}
-
-func main() {
-}
-`))
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-defs/defs.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-defs/defs.go
deleted file mode 100644
index b66d5abdf..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-defs/defs.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// Package defs provides constants required by go-fuzz-build, go-fuzz, and instrumented code.
-package base
-
-// This package has a special interaction with go-fuzz-dep:
-// It is copied into a package with it by go-fuzz-build.
-// Only things that can be safely duplicated without confusion,
-// like constants, should be added to this package.
-// And any additions should be tested carefully. :)
-
-const (
- CoverSize = 64 << 10
- MaxInputSize = 1 << 20
- SonarRegionSize = 1 << 20
-)
-
-const (
- SonarEQL = iota
- SonarNEQ
- SonarLSS
- SonarGTR
- SonarLEQ
- SonarGEQ
-
- SonarOpMask = 7
- SonarLength = 1 << 3
- SonarSigned = 1 << 4
- SonarString = 1 << 5
- SonarConst1 = 1 << 6
- SonarConst2 = 1 << 7
-
- SonarHdrLen = 6
- SonarMaxLen = 20
-)
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/cover.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/cover.go
deleted file mode 100644
index 46604ad5a..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/cover.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build gofuzz
-
-package gofuzzdep
-
-import (
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-// Bool is just a bool.
-// It is used by code autogenerated by go-fuzz-build
-// to avoid compilation errors when a user's code shadows the built-in bool.
-type Bool = bool
-
-// CoverTab holds code coverage.
-// It is initialized to a new array so that instrumentation
-// executed during process initialization has somewhere to write to.
-// It is replaced by a newly initialized array when it is
-// time for actual instrumentation to commence.
-var CoverTab = new([CoverSize]byte)
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/doc.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/doc.go
deleted file mode 100644
index c8adedb38..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/doc.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Package gofuzzdep contains the business logic used to monitor the fuzzing.
-//
-// It is handled specially by go-fuzz-build; see the comments in package go-fuzz-defs.
-//
-// Be particularly careful about adding imports to go-fuzz-dep:
-// Any package imported by go-fuzz-dep cannot be instrumented (on pain of import cycles),
-// which reduces the effectiveness of go-fuzz on any other package that imports it.
-// That is why (e.g.) there are hand-rolled serialization functions instead of using encoding/binary,
-// and hand-rolled syscall-based communication instead of using package net or os.
-package gofuzzdep
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go
deleted file mode 100644
index 09bb3c581..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build gofuzz
-// +build !gofuzz_libfuzzer
-
-package gofuzzdep
-
-import (
- "runtime"
- "sync/atomic"
- "syscall"
- "time"
- "unsafe"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-func Main(fns []func([]byte) int) {
- mem, inFD, outFD := setupCommFile()
- CoverTab = (*[CoverSize]byte)(unsafe.Pointer(&mem[0]))
- input := mem[CoverSize : CoverSize+MaxInputSize]
- sonarRegion = mem[CoverSize+MaxInputSize:]
- runtime.GOMAXPROCS(1) // makes coverage more deterministic, we parallelize on higher level
- for {
- fnidx, n := read(inFD)
- if n > uint64(len(input)) {
- println("invalid input length")
- syscall.Exit(1)
- }
- for i := range CoverTab {
- CoverTab[i] = 0
- }
- atomic.StoreUint32(&sonarPos, 0)
- t0 := time.Now()
- res := fns[fnidx](input[:n:n])
- ns := time.Since(t0)
- write(outFD, uint64(res), uint64(ns), uint64(atomic.LoadUint32(&sonarPos)))
- }
-}
-
-// read reads little-endian-encoded uint8+uint64 from fd.
-func read(fd FD) (uint8, uint64) {
- rd := 0
- var buf [9]byte
- for rd != len(buf) {
- n, err := fd.read(buf[rd:])
- if err == syscall.EINTR {
- continue
- }
- if n == 0 {
- syscall.Exit(1)
- }
- if err != nil {
- println("failed to read fd =", fd, "errno =", err.(syscall.Errno))
- syscall.Exit(1)
- }
- rd += n
- }
- return buf[0], deserialize64(buf[1:])
-}
-
-// write writes little-endian-encoded vals... to fd.
-func write(fd FD, vals ...uint64) {
- var tmp [3 * 8]byte
- buf := tmp[:len(vals)*8]
- for i, v := range vals {
- serialize64(buf[i*8:], v)
- }
- wr := 0
- for wr != len(buf) {
- n, err := fd.write(buf[wr:])
- if err == syscall.EINTR {
- continue
- }
- if err != nil {
- println("failed to read fd =", fd, "errno =", err.(syscall.Errno))
- syscall.Exit(1)
- }
- wr += n
- }
-}
-
-// writeStr writes strings s to fd.
-func writeStr(fd FD, s string) {
- buf := []byte(s)
- wr := 0
- for wr != len(buf) {
- n, err := fd.write(buf[wr:])
- if err == syscall.EINTR {
- continue
- }
- if err != nil {
- println("failed to read fd =", fd, "errno =", err.(syscall.Errno))
- syscall.Exit(1)
- }
- wr += n
- }
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main_libFuzzer.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main_libFuzzer.go
deleted file mode 100644
index 7a4911788..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/main_libFuzzer.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build gofuzz
-// +build gofuzz_libfuzzer
-
-package gofuzzdep
-
-import (
- "unsafe"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-func Initialize(coverTabPtr unsafe.Pointer, coverTabSize uint64) {
- if coverTabSize != CoverSize {
- panic("Incorrect cover tab size")
- }
- CoverTab = (*[CoverSize]byte)(coverTabPtr)
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sonar.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sonar.go
deleted file mode 100644
index e713c6d05..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sonar.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build gofuzz
-
-package gofuzzdep
-
-import (
- "sync/atomic"
- "unsafe"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-var (
- sonarRegion []byte
- sonarPos uint32
-)
-
-const failure = ^uint8(0)
-
-type iface struct {
- typ unsafe.Pointer
- val unsafe.Pointer
-}
-
-// Sonar is called by instrumentation code to notify go-fuzz about comparisons.
-// Low 8 bits of id are flags, the rest is unique id of a comparison.
-func Sonar(v1, v2 interface{}, id uint32) {
- var buf [SonarHdrLen + 2*SonarMaxLen]byte
- n1, f1 := serialize(v1, v2, buf[SonarHdrLen:])
- if n1 == failure {
- return
- }
- n2, f2 := serialize(v2, v1, buf[SonarHdrLen+n1:])
- if n2 == failure {
- return
- }
- // Ideal const operands are converted to signed int,
- // but it does not mean that the comparison is signed
- // unless the other operand is signed.
- if id&SonarConst1 != 0 {
- f1 &^= SonarSigned
- }
- if id&SonarConst2 != 0 {
- f2 &^= SonarSigned
- }
- id |= uint32(f1 | f2)
- serialize32(buf[:], id)
- buf[4] = n1
- buf[5] = n2
- n := uint32(SonarHdrLen + n1 + n2)
- pos := atomic.LoadUint32(&sonarPos)
- for {
- if pos+n > uint32(len(sonarRegion)) {
- return
- }
- if atomic.CompareAndSwapUint32(&sonarPos, pos, pos+n) {
- break
- }
- pos = atomic.LoadUint32(&sonarPos)
- }
- copy(sonarRegion[pos:pos+n], buf[:])
-}
-
-func serialize(v, v2 interface{}, buf []byte) (n, flags uint8) {
- switch vv := v.(type) {
- case int8:
- buf[0] = byte(vv)
- return 1, SonarSigned
- case uint8:
- buf[0] = byte(vv)
- return 1, 0
- case int16:
- return serialize16(buf, uint16(vv)), SonarSigned
- case uint16:
- return serialize16(buf, vv), 0
- case int32:
- return serialize32(buf, uint32(vv)), SonarSigned
- case uint32:
- return serialize32(buf, vv), 0
- case int64:
- return serialize64(buf, uint64(vv)), SonarSigned
- case uint64:
- return serialize64(buf, vv), 0
- case int:
- if unsafe.Sizeof(vv) == 4 {
- return serialize32(buf, uint32(vv)), SonarSigned
- } else {
- return serialize64(buf, uint64(vv)), SonarSigned
- }
- case uint:
- if unsafe.Sizeof(vv) == 4 {
- return serialize32(buf, uint32(vv)), 0
- } else {
- return serialize64(buf, uint64(vv)), 0
- }
- case string:
- if len(vv) > SonarMaxLen {
- return failure, 0
- }
- return uint8(copy(buf, vv)), SonarString
- case [1]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [2]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [3]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [4]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [5]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [6]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [7]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [8]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [9]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [10]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [11]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [12]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [13]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [14]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [15]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [16]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [17]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [18]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [19]byte:
- return uint8(copy(buf, vv[:])), SonarString
- case [20]byte:
- return uint8(copy(buf, vv[:])), SonarString
- default:
- // Special case: string literal is compared with a variable of
- // user type with string underlying type:
- // type Name string
- // var name Name
- // if name == "foo" { ... }
- if _, ok := v2.(string); ok {
- s := *(*string)((*iface)(unsafe.Pointer(&v)).val)
- if len(s) <= SonarMaxLen {
- return uint8(copy(buf[:], s)), SonarString
- }
- }
- return failure, 0
- }
-}
-
-// The serialization routines here match those of encoding/binary.LittleEndian.
-// They are copied here because importing encoding/binary creates import cycles.
-
-func serialize16(buf []byte, v uint16) uint8 {
- _ = buf[1]
- buf[0] = byte(v >> 0)
- buf[1] = byte(v >> 8)
- return 2
-}
-
-func serialize32(buf []byte, v uint32) uint8 {
- _ = buf[3]
- buf[0] = byte(v >> 0)
- buf[1] = byte(v >> 8)
- buf[2] = byte(v >> 16)
- buf[3] = byte(v >> 24)
- return 4
-}
-
-func serialize64(buf []byte, v uint64) uint8 {
- _ = buf[7]
- buf[0] = byte(v >> 0)
- buf[1] = byte(v >> 8)
- buf[2] = byte(v >> 16)
- buf[3] = byte(v >> 24)
- buf[4] = byte(v >> 32)
- buf[5] = byte(v >> 40)
- buf[6] = byte(v >> 48)
- buf[7] = byte(v >> 56)
- return 8
-}
-
-func deserialize64(buf []byte) uint64 {
- _ = buf[7]
- return uint64(buf[0])<<0 |
- uint64(buf[1])<<8 |
- uint64(buf[2])<<16 |
- uint64(buf[3])<<24 |
- uint64(buf[4])<<32 |
- uint64(buf[5])<<40 |
- uint64(buf[6])<<48 |
- uint64(buf[7])<<56
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_posix.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_posix.go
deleted file mode 100644
index 938cf9324..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_posix.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build darwin linux freebsd dragonfly openbsd netbsd
-// +build gofuzz
-
-package gofuzzdep
-
-import (
- "syscall"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-type FD int
-
-func setupCommFile() ([]byte, FD, FD) {
- mem, err := syscall.Mmap(3, 0, CoverSize+MaxInputSize+SonarRegionSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
- if err != nil {
- println("failed to mmap fd = 3 errno =", err.(syscall.Errno))
- syscall.Exit(1)
- }
- return mem, 4, 5
-}
-
-func (fd FD) read(buf []byte) (int, error) {
- return syscall.Read(int(fd), buf)
-}
-
-func (fd FD) write(buf []byte) (int, error) {
- return syscall.Write(int(fd), buf)
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_windows.go b/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_windows.go
deleted file mode 100644
index 160301549..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/go-fuzz-dep/sys_windows.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// +build gofuzz
-
-package gofuzzdep
-
-import (
- "syscall"
- "unsafe"
-
- . "github.com/dvyukov/go-fuzz/go-fuzz-defs"
-)
-
-// Can't import reflect because of import cycles.
-type sliceHeader struct {
- addr uintptr
- l, c int
-}
-
-type FD syscall.Handle
-
-func setupCommFile() ([]byte, FD, FD) {
- const (
- size = CoverSize + MaxInputSize + SonarRegionSize
- FILE_MAP_ALL_ACCESS = 0xF001F
- )
- mapping := readEnvParam("GO_FUZZ_COMM_FD")
- addr, err := syscall.MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, size)
- if err != nil {
- println("failed to mmap comm file:", err.Error())
- syscall.Exit(1)
- }
- hdr := sliceHeader{addr, size, size}
- mem := *(*[]byte)(unsafe.Pointer(&hdr))
- in := FD(readEnvParam("GO_FUZZ_IN_FD"))
- out := FD(readEnvParam("GO_FUZZ_OUT_FD"))
- return mem, in, out
-}
-
-func readEnvParam(name string) syscall.Handle {
- v, _ := syscall.Getenv(name)
- var x uintptr
- for i := 0; i < len(v); i++ {
- x = x*10 + uintptr(v[i]-'0')
- }
- return syscall.Handle(x)
-}
-
-func (fd FD) read(buf []byte) (int, error) {
- return syscall.Read(syscall.Handle(fd), buf)
-}
-
-func (fd FD) write(buf []byte) (int, error) {
- return syscall.Write(syscall.Handle(fd), buf)
-}
diff --git a/vendor/github.com/dvyukov/go-fuzz/internal/go-fuzz-types/types.go b/vendor/github.com/dvyukov/go-fuzz/internal/go-fuzz-types/types.go
deleted file mode 100644
index 360481ff2..000000000
--- a/vendor/github.com/dvyukov/go-fuzz/internal/go-fuzz-types/types.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 go-fuzz project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-// Package types provides types shared between go-fuzz-build and go-fuzz.
-package types
-
-type CoverBlock struct {
- ID int
- File string
- StartLine int
- StartCol int
- EndLine int
- EndCol int
- NumStmt int
-}
-
-type Literal struct {
- Val string
- IsStr bool
-}
-
-type MetaData struct {
- Literals []Literal
- Blocks []CoverBlock
- Sonar []CoverBlock
- Funcs []string // fuzz function names; must have length > 0
- DefaultFunc string // default function to fuzz
-}