17f904d7eSThomas Gleixner// SPDX-License-Identifier: GPL-2.0-only
27703692eSNicolas Palix///
37c2aa611SJulia Lawall/// A variable is dereferenced under a NULL test.
47c2aa611SJulia Lawall/// Even though it is known to be NULL.
57703692eSNicolas Palix///
67703692eSNicolas Palix// Confidence: Moderate
77f904d7eSThomas Gleixner// Copyright: (C) 2010 Nicolas Palix, DIKU.
87f904d7eSThomas Gleixner// Copyright: (C) 2010 Julia Lawall, DIKU.
97f904d7eSThomas Gleixner// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
10*f01701ceSJulia Lawall// URL: https://coccinelle.gitlabpages.inria.fr/website
117703692eSNicolas Palix// Comments: -I ... -all_includes can give more complete results
127703692eSNicolas Palix// Options:
137703692eSNicolas Palix
147703692eSNicolas Palixvirtual context
157703692eSNicolas Palixvirtual org
167703692eSNicolas Palixvirtual report
177703692eSNicolas Palix
187703692eSNicolas Palix// The following two rules are separate, because both can match a single
197703692eSNicolas Palix// expression in different ways
20a1087ef6SJulia Lawall@pr1 expression@
2121195f8eSJulia Lawallexpression E;
227703692eSNicolas Palixidentifier f;
237703692eSNicolas Palixposition p1;
247703692eSNicolas Palix@@
257703692eSNicolas Palix
267703692eSNicolas Palix (E != NULL && ...) ? <+...E->f@p1...+> : ...
277703692eSNicolas Palix
28a1087ef6SJulia Lawall@pr2 expression@
2921195f8eSJulia Lawallexpression E;
307703692eSNicolas Palixidentifier f;
317703692eSNicolas Palixposition p2;
327703692eSNicolas Palix@@
337703692eSNicolas Palix
347703692eSNicolas Palix(
357703692eSNicolas Palix  (E != NULL) && ... && <+...E->f@p2...+>
367703692eSNicolas Palix|
377703692eSNicolas Palix  (E == NULL) || ... || <+...E->f@p2...+>
387703692eSNicolas Palix|
397703692eSNicolas Palix sizeof(<+...E->f@p2...+>)
407703692eSNicolas Palix)
417703692eSNicolas Palix
4221195f8eSJulia Lawall@ifm@
4321195f8eSJulia Lawallexpression *E;
4421195f8eSJulia Lawallstatement S1,S2;
4521195f8eSJulia Lawallposition p1;
4621195f8eSJulia Lawall@@
4721195f8eSJulia Lawall
4821195f8eSJulia Lawallif@p1 ((E == NULL && ...) || ...) S1 else S2
4921195f8eSJulia Lawall
507703692eSNicolas Palix// For org and report modes
517703692eSNicolas Palix
52a1087ef6SJulia Lawall@r depends on !context && (org || report) exists@
537703692eSNicolas Palixexpression subE <= ifm.E;
547703692eSNicolas Palixexpression *ifm.E;
557703692eSNicolas Palixexpression E1,E2;
567703692eSNicolas Palixidentifier f;
577703692eSNicolas Palixstatement S1,S2,S3,S4;
587703692eSNicolas Palixiterator iter;
597703692eSNicolas Palixposition p!={pr1.p1,pr2.p2};
607703692eSNicolas Palixposition ifm.p1;
617703692eSNicolas Palix@@
627703692eSNicolas Palix
637703692eSNicolas Palixif@p1 ((E == NULL && ...) || ...)
647703692eSNicolas Palix{
657703692eSNicolas Palix  ... when != if (...) S1 else S2
667703692eSNicolas Palix(
677703692eSNicolas Palix iter(subE,...) S4 // no use
687703692eSNicolas Palix|
697703692eSNicolas Palix list_remove_head(E2,subE,...)
707703692eSNicolas Palix|
717703692eSNicolas Palix subE = E1
727703692eSNicolas Palix|
737703692eSNicolas Palix for(subE = E1;...;...) S4
747703692eSNicolas Palix|
757703692eSNicolas Palix subE++
767703692eSNicolas Palix|
777703692eSNicolas Palix ++subE
787703692eSNicolas Palix|
797703692eSNicolas Palix --subE
807703692eSNicolas Palix|
817703692eSNicolas Palix subE--
827703692eSNicolas Palix|
837703692eSNicolas Palix &subE
847703692eSNicolas Palix|
857703692eSNicolas Palix E->f@p // bad use
867703692eSNicolas Palix)
877703692eSNicolas Palix  ... when any
887703692eSNicolas Palix  return ...;
897703692eSNicolas Palix}
907703692eSNicolas Palixelse S3
917703692eSNicolas Palix
92a1087ef6SJulia Lawall@script:python depends on !context && !org && report@
937703692eSNicolas Palixp << r.p;
947703692eSNicolas Palixp1 << ifm.p1;
957703692eSNicolas Palixx << ifm.E;
967703692eSNicolas Palix@@
977703692eSNicolas Palix
987703692eSNicolas Palixmsg="ERROR: %s is NULL but dereferenced." % (x)
997703692eSNicolas Palixcoccilib.report.print_report(p[0], msg)
1007703692eSNicolas Palixcocci.include_match(False)
1017703692eSNicolas Palix
102a1087ef6SJulia Lawall@script:python depends on !context && org && !report@
1037703692eSNicolas Palixp << r.p;
1047703692eSNicolas Palixp1 << ifm.p1;
1057703692eSNicolas Palixx << ifm.E;
1067703692eSNicolas Palix@@
1077703692eSNicolas Palix
1087703692eSNicolas Palixmsg="ERROR: %s is NULL but dereferenced." % (x)
1097703692eSNicolas Palixmsg_safe=msg.replace("[","@(").replace("]",")")
1107703692eSNicolas Palixcocci.print_main(msg_safe,p)
1117703692eSNicolas Palixcocci.include_match(False)
1127703692eSNicolas Palix
113a1087ef6SJulia Lawall@s depends on !context && (org || report) exists@
1147703692eSNicolas Palixexpression subE <= ifm.E;
1157703692eSNicolas Palixexpression *ifm.E;
1167703692eSNicolas Palixexpression E1,E2;
1177703692eSNicolas Palixidentifier f;
1187703692eSNicolas Palixstatement S1,S2,S3,S4;
1197703692eSNicolas Palixiterator iter;
1207703692eSNicolas Palixposition p!={pr1.p1,pr2.p2};
1217703692eSNicolas Palixposition ifm.p1;
1227703692eSNicolas Palix@@
1237703692eSNicolas Palix
1247703692eSNicolas Palixif@p1 ((E == NULL && ...) || ...)
1257703692eSNicolas Palix{
1267703692eSNicolas Palix  ... when != if (...) S1 else S2
1277703692eSNicolas Palix(
1287703692eSNicolas Palix iter(subE,...) S4 // no use
1297703692eSNicolas Palix|
1307703692eSNicolas Palix list_remove_head(E2,subE,...)
1317703692eSNicolas Palix|
1327703692eSNicolas Palix subE = E1
1337703692eSNicolas Palix|
1347703692eSNicolas Palix for(subE = E1;...;...) S4
1357703692eSNicolas Palix|
1367703692eSNicolas Palix subE++
1377703692eSNicolas Palix|
1387703692eSNicolas Palix ++subE
1397703692eSNicolas Palix|
1407703692eSNicolas Palix --subE
1417703692eSNicolas Palix|
1427703692eSNicolas Palix subE--
1437703692eSNicolas Palix|
1447703692eSNicolas Palix &subE
1457703692eSNicolas Palix|
1467703692eSNicolas Palix E->f@p // bad use
1477703692eSNicolas Palix)
1487703692eSNicolas Palix  ... when any
1497703692eSNicolas Palix}
1507703692eSNicolas Palixelse S3
1517703692eSNicolas Palix
152a1087ef6SJulia Lawall@script:python depends on !context && !org && report@
1537703692eSNicolas Palixp << s.p;
1547703692eSNicolas Palixp1 << ifm.p1;
1557703692eSNicolas Palixx << ifm.E;
1567703692eSNicolas Palix@@
1577703692eSNicolas Palix
1587703692eSNicolas Palixmsg="ERROR: %s is NULL but dereferenced." % (x)
1597703692eSNicolas Palixcoccilib.report.print_report(p[0], msg)
1607703692eSNicolas Palix
161a1087ef6SJulia Lawall@script:python depends on !context && org && !report@
1627703692eSNicolas Palixp << s.p;
1637703692eSNicolas Palixp1 << ifm.p1;
1647703692eSNicolas Palixx << ifm.E;
1657703692eSNicolas Palix@@
1667703692eSNicolas Palix
1677703692eSNicolas Palixmsg="ERROR: %s is NULL but dereferenced." % (x)
1687703692eSNicolas Palixmsg_safe=msg.replace("[","@(").replace("]",")")
1697703692eSNicolas Palixcocci.print_main(msg_safe,p)
1707703692eSNicolas Palix
1717703692eSNicolas Palix// For context mode
1727703692eSNicolas Palix
173a1087ef6SJulia Lawall@depends on context && !org && !report exists@
1747703692eSNicolas Palixexpression subE <= ifm.E;
1757703692eSNicolas Palixexpression *ifm.E;
1767703692eSNicolas Palixexpression E1,E2;
1777703692eSNicolas Palixidentifier f;
1787703692eSNicolas Palixstatement S1,S2,S3,S4;
1797703692eSNicolas Palixiterator iter;
1807703692eSNicolas Palixposition p!={pr1.p1,pr2.p2};
1817703692eSNicolas Palixposition ifm.p1;
1827703692eSNicolas Palix@@
1837703692eSNicolas Palix
1847703692eSNicolas Palixif@p1 ((E == NULL && ...) || ...)
1857703692eSNicolas Palix{
1867703692eSNicolas Palix  ... when != if (...) S1 else S2
1877703692eSNicolas Palix(
1887703692eSNicolas Palix iter(subE,...) S4 // no use
1897703692eSNicolas Palix|
1907703692eSNicolas Palix list_remove_head(E2,subE,...)
1917703692eSNicolas Palix|
1927703692eSNicolas Palix subE = E1
1937703692eSNicolas Palix|
1947703692eSNicolas Palix for(subE = E1;...;...) S4
1957703692eSNicolas Palix|
1967703692eSNicolas Palix subE++
1977703692eSNicolas Palix|
1987703692eSNicolas Palix ++subE
1997703692eSNicolas Palix|
2007703692eSNicolas Palix --subE
2017703692eSNicolas Palix|
2027703692eSNicolas Palix subE--
2037703692eSNicolas Palix|
2047703692eSNicolas Palix &subE
2057703692eSNicolas Palix|
2067703692eSNicolas Palix* E->f@p // bad use
2077703692eSNicolas Palix)
2087703692eSNicolas Palix  ... when any
2097703692eSNicolas Palix  return ...;
2107703692eSNicolas Palix}
2117703692eSNicolas Palixelse S3
2127703692eSNicolas Palix
2137703692eSNicolas Palix// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
2147703692eSNicolas Palix// It is need because the previous rule as already made a "change".
2157703692eSNicolas Palix
216a2b0fe74SJulia Lawall@pr11 depends on context && !org && !report expression@
21721195f8eSJulia Lawallexpression E;
2187703692eSNicolas Palixidentifier f;
2197703692eSNicolas Palixposition p1;
2207703692eSNicolas Palix@@
2217703692eSNicolas Palix
2227703692eSNicolas Palix (E != NULL && ...) ? <+...E->f@p1...+> : ...
2237703692eSNicolas Palix
224a2b0fe74SJulia Lawall@pr12 depends on context && !org && !report expression@
22521195f8eSJulia Lawallexpression E;
2267703692eSNicolas Palixidentifier f;
2277703692eSNicolas Palixposition p2;
2287703692eSNicolas Palix@@
2297703692eSNicolas Palix
2307703692eSNicolas Palix(
2317703692eSNicolas Palix  (E != NULL) && ... && <+...E->f@p2...+>
2327703692eSNicolas Palix|
2337703692eSNicolas Palix  (E == NULL) || ... || <+...E->f@p2...+>
2347703692eSNicolas Palix|
2357703692eSNicolas Palix sizeof(<+...E->f@p2...+>)
2367703692eSNicolas Palix)
2377703692eSNicolas Palix
23821195f8eSJulia Lawall@ifm1 depends on context && !org && !report@
23921195f8eSJulia Lawallexpression *E;
24021195f8eSJulia Lawallstatement S1,S2;
24121195f8eSJulia Lawallposition p1;
24221195f8eSJulia Lawall@@
24321195f8eSJulia Lawall
24421195f8eSJulia Lawallif@p1 ((E == NULL && ...) || ...) S1 else S2
24521195f8eSJulia Lawall
246a1087ef6SJulia Lawall@depends on context && !org && !report exists@
2477703692eSNicolas Palixexpression subE <= ifm1.E;
2487703692eSNicolas Palixexpression *ifm1.E;
2497703692eSNicolas Palixexpression E1,E2;
2507703692eSNicolas Palixidentifier f;
2517703692eSNicolas Palixstatement S1,S2,S3,S4;
2527703692eSNicolas Palixiterator iter;
2537703692eSNicolas Palixposition p!={pr11.p1,pr12.p2};
2547703692eSNicolas Palixposition ifm1.p1;
2557703692eSNicolas Palix@@
2567703692eSNicolas Palix
2577703692eSNicolas Palixif@p1 ((E == NULL && ...) || ...)
2587703692eSNicolas Palix{
2597703692eSNicolas Palix  ... when != if (...) S1 else S2
2607703692eSNicolas Palix(
2617703692eSNicolas Palix iter(subE,...) S4 // no use
2627703692eSNicolas Palix|
2637703692eSNicolas Palix list_remove_head(E2,subE,...)
2647703692eSNicolas Palix|
2657703692eSNicolas Palix subE = E1
2667703692eSNicolas Palix|
2677703692eSNicolas Palix for(subE = E1;...;...) S4
2687703692eSNicolas Palix|
2697703692eSNicolas Palix subE++
2707703692eSNicolas Palix|
2717703692eSNicolas Palix ++subE
2727703692eSNicolas Palix|
2737703692eSNicolas Palix --subE
2747703692eSNicolas Palix|
2757703692eSNicolas Palix subE--
2767703692eSNicolas Palix|
2777703692eSNicolas Palix &subE
2787703692eSNicolas Palix|
2797703692eSNicolas Palix* E->f@p // bad use
2807703692eSNicolas Palix)
2817703692eSNicolas Palix  ... when any
2827703692eSNicolas Palix}
2837703692eSNicolas Palixelse S3
284