0001 // SPDX-License-Identifier: GPL-2.0-only
0002 ///
0003 /// A variable is dereferenced under a NULL test.
0004 /// Even though it is known to be NULL.
0005 ///
0006 // Confidence: Moderate
0007 // Copyright: (C) 2010 Nicolas Palix, DIKU.
0008 // Copyright: (C) 2010 Julia Lawall, DIKU.
0009 // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.
0010 // URL: https://coccinelle.gitlabpages.inria.fr/website
0011 // Comments: -I ... -all_includes can give more complete results
0012 // Options:
0013
0014 virtual context
0015 virtual org
0016 virtual report
0017
0018 // The following two rules are separate, because both can match a single
0019 // expression in different ways
0020 @pr1 expression@
0021 expression E;
0022 identifier f;
0023 position p1;
0024 @@
0025
0026 (E != NULL && ...) ? <+...E->f@p1...+> : ...
0027
0028 @pr2 expression@
0029 expression E;
0030 identifier f;
0031 position p2;
0032 @@
0033
0034 (
0035 (E != NULL) && ... && <+...E->f@p2...+>
0036 |
0037 (E == NULL) || ... || <+...E->f@p2...+>
0038 |
0039 sizeof(<+...E->f@p2...+>)
0040 )
0041
0042 @ifm@
0043 expression *E;
0044 statement S1,S2;
0045 position p1;
0046 @@
0047
0048 if@p1 ((E == NULL && ...) || ...) S1 else S2
0049
0050 // For org and report modes
0051
0052 @r depends on !context && (org || report) exists@
0053 expression subE <= ifm.E;
0054 expression *ifm.E;
0055 expression E1,E2;
0056 identifier f;
0057 statement S1,S2,S3,S4;
0058 iterator iter;
0059 position p!={pr1.p1,pr2.p2};
0060 position ifm.p1;
0061 @@
0062
0063 if@p1 ((E == NULL && ...) || ...)
0064 {
0065 ... when != if (...) S1 else S2
0066 (
0067 iter(subE,...) S4 // no use
0068 |
0069 list_remove_head(E2,subE,...)
0070 |
0071 subE = E1
0072 |
0073 for(subE = E1;...;...) S4
0074 |
0075 subE++
0076 |
0077 ++subE
0078 |
0079 --subE
0080 |
0081 subE--
0082 |
0083 &subE
0084 |
0085 E->f@p // bad use
0086 )
0087 ... when any
0088 return ...;
0089 }
0090 else S3
0091
0092 @script:python depends on !context && !org && report@
0093 p << r.p;
0094 p1 << ifm.p1;
0095 x << ifm.E;
0096 @@
0097
0098 msg="ERROR: %s is NULL but dereferenced." % (x)
0099 coccilib.report.print_report(p[0], msg)
0100 cocci.include_match(False)
0101
0102 @script:python depends on !context && org && !report@
0103 p << r.p;
0104 p1 << ifm.p1;
0105 x << ifm.E;
0106 @@
0107
0108 msg="ERROR: %s is NULL but dereferenced." % (x)
0109 msg_safe=msg.replace("[","@(").replace("]",")")
0110 cocci.print_main(msg_safe,p)
0111 cocci.include_match(False)
0112
0113 @s depends on !context && (org || report) exists@
0114 expression subE <= ifm.E;
0115 expression *ifm.E;
0116 expression E1,E2;
0117 identifier f;
0118 statement S1,S2,S3,S4;
0119 iterator iter;
0120 position p!={pr1.p1,pr2.p2};
0121 position ifm.p1;
0122 @@
0123
0124 if@p1 ((E == NULL && ...) || ...)
0125 {
0126 ... when != if (...) S1 else S2
0127 (
0128 iter(subE,...) S4 // no use
0129 |
0130 list_remove_head(E2,subE,...)
0131 |
0132 subE = E1
0133 |
0134 for(subE = E1;...;...) S4
0135 |
0136 subE++
0137 |
0138 ++subE
0139 |
0140 --subE
0141 |
0142 subE--
0143 |
0144 &subE
0145 |
0146 E->f@p // bad use
0147 )
0148 ... when any
0149 }
0150 else S3
0151
0152 @script:python depends on !context && !org && report@
0153 p << s.p;
0154 p1 << ifm.p1;
0155 x << ifm.E;
0156 @@
0157
0158 msg="ERROR: %s is NULL but dereferenced." % (x)
0159 coccilib.report.print_report(p[0], msg)
0160
0161 @script:python depends on !context && org && !report@
0162 p << s.p;
0163 p1 << ifm.p1;
0164 x << ifm.E;
0165 @@
0166
0167 msg="ERROR: %s is NULL but dereferenced." % (x)
0168 msg_safe=msg.replace("[","@(").replace("]",")")
0169 cocci.print_main(msg_safe,p)
0170
0171 // For context mode
0172
0173 @depends on context && !org && !report exists@
0174 expression subE <= ifm.E;
0175 expression *ifm.E;
0176 expression E1,E2;
0177 identifier f;
0178 statement S1,S2,S3,S4;
0179 iterator iter;
0180 position p!={pr1.p1,pr2.p2};
0181 position ifm.p1;
0182 @@
0183
0184 if@p1 ((E == NULL && ...) || ...)
0185 {
0186 ... when != if (...) S1 else S2
0187 (
0188 iter(subE,...) S4 // no use
0189 |
0190 list_remove_head(E2,subE,...)
0191 |
0192 subE = E1
0193 |
0194 for(subE = E1;...;...) S4
0195 |
0196 subE++
0197 |
0198 ++subE
0199 |
0200 --subE
0201 |
0202 subE--
0203 |
0204 &subE
0205 |
0206 * E->f@p // bad use
0207 )
0208 ... when any
0209 return ...;
0210 }
0211 else S3
0212
0213 // The following three rules are duplicates of ifm, pr1 and pr2 respectively.
0214 // It is need because the previous rule as already made a "change".
0215
0216 @pr11 depends on context && !org && !report expression@
0217 expression E;
0218 identifier f;
0219 position p1;
0220 @@
0221
0222 (E != NULL && ...) ? <+...E->f@p1...+> : ...
0223
0224 @pr12 depends on context && !org && !report expression@
0225 expression E;
0226 identifier f;
0227 position p2;
0228 @@
0229
0230 (
0231 (E != NULL) && ... && <+...E->f@p2...+>
0232 |
0233 (E == NULL) || ... || <+...E->f@p2...+>
0234 |
0235 sizeof(<+...E->f@p2...+>)
0236 )
0237
0238 @ifm1 depends on context && !org && !report@
0239 expression *E;
0240 statement S1,S2;
0241 position p1;
0242 @@
0243
0244 if@p1 ((E == NULL && ...) || ...) S1 else S2
0245
0246 @depends on context && !org && !report exists@
0247 expression subE <= ifm1.E;
0248 expression *ifm1.E;
0249 expression E1,E2;
0250 identifier f;
0251 statement S1,S2,S3,S4;
0252 iterator iter;
0253 position p!={pr11.p1,pr12.p2};
0254 position ifm1.p1;
0255 @@
0256
0257 if@p1 ((E == NULL && ...) || ...)
0258 {
0259 ... when != if (...) S1 else S2
0260 (
0261 iter(subE,...) S4 // no use
0262 |
0263 list_remove_head(E2,subE,...)
0264 |
0265 subE = E1
0266 |
0267 for(subE = E1;...;...) S4
0268 |
0269 subE++
0270 |
0271 ++subE
0272 |
0273 --subE
0274 |
0275 subE--
0276 |
0277 &subE
0278 |
0279 * E->f@p // bad use
0280 )
0281 ... when any
0282 }
0283 else S3