68
68
type resInfo struct {
69
69
Valid bool
70
70
Funcs []string
71
+
72
+ // reuse for doc
73
+ ReqCtx bool
74
+ Skip bool
71
75
}
72
76
73
77
type ctxFact map [string ]resInfo
@@ -238,24 +242,45 @@ func (r *runner) checkIsEntry(f *ssa.Function) entryType {
238
242
return EntryWithCtx
239
243
}
240
244
245
+ reqctx , skip := r .docFlag (f )
246
+
241
247
// check is `func handler(w http.ResponseWriter, r *http.Request) {}`
242
- if r .checkIsHttpHandler (f ) {
248
+ // or use '// @contextcheck(req_has_ctx)'
249
+ if r .checkIsHttpHandler (f , reqctx ) {
243
250
return EntryWithHttpHandler
244
251
}
245
252
246
- if r . skipByNolint ( f ) {
253
+ if skip {
247
254
return EntryNone
248
255
}
249
256
250
257
return EntryNormal
251
258
}
252
259
260
+ func (r * runner ) docFlag (f * ssa.Function ) (reqctx , skip bool ) {
261
+ key := "doc:" + f .RelString (nil )
262
+ res , ok := r .getValue (key , f )
263
+ if ok {
264
+ return res .ReqCtx , res .Skip
265
+ }
266
+
267
+ for _ , v := range r .getDocFromFunc (f ) {
268
+ if len (nolintRe .FindString (v .Text )) > 0 && strings .Contains (v .Text , "contextcheck" ) {
269
+ res .Skip = true
270
+ } else if strings .HasPrefix (v .Text , "// @contextcheck(req_has_ctx)" ) {
271
+ res .ReqCtx = true
272
+ }
273
+ }
274
+ r .currentFact [key ] = res
275
+ return res .ReqCtx , res .Skip
276
+ }
277
+
253
278
var nolintRe = regexp .MustCompile (`^//\s?nolint:` )
254
279
255
- func (r * runner ) skipByNolint (f * ssa.Function ) bool {
280
+ func (r * runner ) getDocFromFunc (f * ssa.Function ) [] * ast. Comment {
256
281
file := analysisutil .File (r .pass , f .Pos ())
257
282
if file == nil {
258
- return false
283
+ return nil
259
284
}
260
285
261
286
// only support FuncDecl comment
@@ -267,15 +292,9 @@ func (r *runner) skipByNolint(f *ssa.Function) bool {
267
292
}
268
293
}
269
294
if fd == nil || fd .Doc == nil || len (fd .Doc .List ) == 0 {
270
- return false
271
- }
272
-
273
- for _ , v := range fd .Doc .List {
274
- if len (nolintRe .FindString (v .Text )) > 0 && strings .Contains (v .Text , "contextcheck" ) {
275
- return true
276
- }
295
+ return nil
277
296
}
278
- return false
297
+ return fd . Doc . List
279
298
}
280
299
281
300
func (r * runner ) checkIsCtx (f * ssa.Function ) (in , out bool ) {
@@ -307,7 +326,16 @@ func (r *runner) checkIsCtx(f *ssa.Function) (in, out bool) {
307
326
return
308
327
}
309
328
310
- func (r * runner ) checkIsHttpHandler (f * ssa.Function ) bool {
329
+ func (r * runner ) checkIsHttpHandler (f * ssa.Function , reqctx bool ) bool {
330
+ if reqctx {
331
+ tuple := f .Signature .Params ()
332
+ for i := 0 ; i < tuple .Len (); i ++ {
333
+ if r .isHttpReqType (tuple .At (i ).Type ()) {
334
+ return true
335
+ }
336
+ }
337
+ }
338
+
311
339
// must has no result
312
340
if f .Signature .Results ().Len () > 0 {
313
341
return false
0 commit comments