@@ -99,6 +99,8 @@ func checkFuzz(pass *analysis.Pass, fn *ast.FuncDecl) {
99
99
// 4. Second argument onwards should be of type []byte, string, bool, byte,
100
100
// rune, float32, float64, int, int8, int16, int32, int64, uint, uint8, uint16,
101
101
// uint32, uint64
102
+ // 5. func() must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip
103
+ // The only *F methods that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
102
104
// Returns the list of parameters to the fuzz function, if they are valid fuzz parameters.
103
105
func checkFuzzCall (pass * analysis.Pass , fn * ast.FuncDecl ) (params * types.Tuple ) {
104
106
ast .Inspect (fn , func (n ast.Node ) bool {
@@ -121,7 +123,7 @@ func checkFuzzCall(pass *analysis.Pass, fn *ast.FuncDecl) (params *types.Tuple)
121
123
// Argument should be a function
122
124
if ! argOk {
123
125
pass .ReportRangef (expr , "argument to Fuzz must be a function" )
124
- return true
126
+ return false
125
127
}
126
128
// ff Argument function should not return
127
129
if tSign .Results ().Len () != 0 {
@@ -130,12 +132,28 @@ func checkFuzzCall(pass *analysis.Pass, fn *ast.FuncDecl) (params *types.Tuple)
130
132
// ff Argument function should have 1 or more argument
131
133
if tSign .Params ().Len () == 0 {
132
134
pass .ReportRangef (expr , "fuzz target must have 1 or more argument" )
133
- return true
135
+ return false
134
136
}
135
137
ok := validateFuzzArgs (pass , tSign .Params (), expr )
136
138
if ok && params == nil {
137
139
params = tSign .Params ()
138
140
}
141
+ // Inspect the function that was passed as an argument to make sure that
142
+ // there are no calls to *F methods, except for Name and Failed.
143
+ ast .Inspect (expr , func (n ast.Node ) bool {
144
+ if call , ok := n .(* ast.CallExpr ); ok {
145
+ if ! isFuzzTargetDot (pass , call , "" ) {
146
+ return true
147
+ }
148
+ if ! isFuzzTargetDot (pass , call , "Name" ) && ! isFuzzTargetDot (pass , call , "Failed" ) {
149
+ pass .ReportRangef (call , "fuzz target must not call any *F methods" )
150
+ }
151
+ }
152
+ return true
153
+ })
154
+ // We do not need to look at any calls to f.Fuzz inside of a Fuzz call,
155
+ // since they are not allowed.
156
+ return false
139
157
}
140
158
return true
141
159
})
@@ -202,7 +220,7 @@ func isFuzzTargetDot(pass *analysis.Pass, call *ast.CallExpr, name string) bool
202
220
if ! isTestingType (pass .TypesInfo .Types [selExpr .X ].Type , "F" ) {
203
221
return false
204
222
}
205
- if selExpr .Sel .Name == name {
223
+ if name == "" || selExpr .Sel .Name == name {
206
224
return true
207
225
}
208
226
}
0 commit comments