1*4882a593Smuzhiyun// SPDX-License-Identifier: GPL-2.0-only 2*4882a593Smuzhiyun/// Many iterators have the property that the first argument is always bound 3*4882a593Smuzhiyun/// to a real list element, never NULL. 4*4882a593Smuzhiyun//# False positives arise for some iterators that do not have this property, 5*4882a593Smuzhiyun//# or in cases when the loop cursor is reassigned. The latter should only 6*4882a593Smuzhiyun//# happen when the matched code is on the way to a loop exit (break, goto, 7*4882a593Smuzhiyun//# or return). 8*4882a593Smuzhiyun/// 9*4882a593Smuzhiyun// Confidence: Moderate 10*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Nicolas Palix. 11*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. 12*4882a593Smuzhiyun// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. 13*4882a593Smuzhiyun// URL: http://coccinelle.lip6.fr/ 14*4882a593Smuzhiyun// Comments: 15*4882a593Smuzhiyun// Options: --no-includes --include-headers 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunvirtual patch 18*4882a593Smuzhiyunvirtual context 19*4882a593Smuzhiyunvirtual org 20*4882a593Smuzhiyunvirtual report 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun@depends on patch@ 23*4882a593Smuzhiyuniterator I; 24*4882a593Smuzhiyunexpression x,E,E1,E2; 25*4882a593Smuzhiyunstatement S,S1,S2; 26*4882a593Smuzhiyun@@ 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunI(x,...) { <... 29*4882a593Smuzhiyun( 30*4882a593Smuzhiyun- if (x == NULL && ...) S 31*4882a593Smuzhiyun| 32*4882a593Smuzhiyun- if (x != NULL || ...) 33*4882a593Smuzhiyun S 34*4882a593Smuzhiyun| 35*4882a593Smuzhiyun- (x == NULL) || 36*4882a593Smuzhiyun E 37*4882a593Smuzhiyun| 38*4882a593Smuzhiyun- (x != NULL) && 39*4882a593Smuzhiyun E 40*4882a593Smuzhiyun| 41*4882a593Smuzhiyun- (x == NULL && ...) ? E1 : 42*4882a593Smuzhiyun E2 43*4882a593Smuzhiyun| 44*4882a593Smuzhiyun- (x != NULL || ...) ? 45*4882a593Smuzhiyun E1 46*4882a593Smuzhiyun- : E2 47*4882a593Smuzhiyun| 48*4882a593Smuzhiyun- if (x == NULL && ...) S1 else 49*4882a593Smuzhiyun S2 50*4882a593Smuzhiyun| 51*4882a593Smuzhiyun- if (x != NULL || ...) 52*4882a593Smuzhiyun S1 53*4882a593Smuzhiyun- else S2 54*4882a593Smuzhiyun| 55*4882a593Smuzhiyun+ BAD( 56*4882a593Smuzhiyun x == NULL 57*4882a593Smuzhiyun+ ) 58*4882a593Smuzhiyun| 59*4882a593Smuzhiyun+ BAD( 60*4882a593Smuzhiyun x != NULL 61*4882a593Smuzhiyun+ ) 62*4882a593Smuzhiyun) 63*4882a593Smuzhiyun ...> } 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun@r depends on !patch exists@ 66*4882a593Smuzhiyuniterator I; 67*4882a593Smuzhiyunexpression x,E; 68*4882a593Smuzhiyunposition p1,p2; 69*4882a593Smuzhiyun@@ 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun*I@p1(x,...) 72*4882a593Smuzhiyun{ ... when != x = E 73*4882a593Smuzhiyun( 74*4882a593Smuzhiyun* x@p2 == NULL 75*4882a593Smuzhiyun| 76*4882a593Smuzhiyun* x@p2 != NULL 77*4882a593Smuzhiyun) 78*4882a593Smuzhiyun ... when any 79*4882a593Smuzhiyun} 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun@script:python depends on org@ 82*4882a593Smuzhiyunp1 << r.p1; 83*4882a593Smuzhiyunp2 << r.p2; 84*4882a593Smuzhiyun@@ 85*4882a593Smuzhiyun 86*4882a593Smuzhiyuncocci.print_main("iterator-bound variable",p1) 87*4882a593Smuzhiyuncocci.print_secs("useless NULL test",p2) 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun@script:python depends on report@ 90*4882a593Smuzhiyunp1 << r.p1; 91*4882a593Smuzhiyunp2 << r.p2; 92*4882a593Smuzhiyun@@ 93*4882a593Smuzhiyun 94*4882a593Smuzhiyunmsg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line) 95*4882a593Smuzhiyuncoccilib.report.print_report(p2[0], msg) 96