xref: /llvm-project/clang/test/Analysis/inlining/inline-defensive-checks.c (revision 95f9a68b1f8fa4d9a93b8eb5abc5c5c9bc58ee5b)
1184c6242SDominic Chen // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
28d7c8a4dSAnna Zaks 
38d7c8a4dSAnna Zaks // Perform inline defensive checks.
idc(void * p)437de8888SArtem Dergachev void idc(void *p) {
58d7c8a4dSAnna Zaks 	if (p)
68d7c8a4dSAnna Zaks 		;
78d7c8a4dSAnna Zaks }
88d7c8a4dSAnna Zaks 
test01(int * p)98d7c8a4dSAnna Zaks int test01(int *p) {
108d7c8a4dSAnna Zaks   if (p)
118d7c8a4dSAnna Zaks     ;
128d7c8a4dSAnna Zaks   return *p; // expected-warning {{Dereference of null pointer}}
138d7c8a4dSAnna Zaks }
148d7c8a4dSAnna Zaks 
test02(int * p,int * x)158d7c8a4dSAnna Zaks int test02(int *p, int *x) {
168d7c8a4dSAnna Zaks   if (p)
178d7c8a4dSAnna Zaks     ;
188d7c8a4dSAnna Zaks   idc(p);
198d7c8a4dSAnna Zaks 	if (x)
208d7c8a4dSAnna Zaks 		;
218d7c8a4dSAnna Zaks   return *p; // expected-warning {{Dereference of null pointer}}
228d7c8a4dSAnna Zaks }
238d7c8a4dSAnna Zaks 
test03(int * p,int * x)248d7c8a4dSAnna Zaks int test03(int *p, int *x) {
258d7c8a4dSAnna Zaks 	idc(p);
268d7c8a4dSAnna Zaks 	if (p)
278d7c8a4dSAnna Zaks 		;
288d7c8a4dSAnna Zaks 	return *p; // False negative
298d7c8a4dSAnna Zaks }
308d7c8a4dSAnna Zaks 
deref04(int * p)318d7c8a4dSAnna Zaks int deref04(int *p) {
328d7c8a4dSAnna Zaks   return *p; // expected-warning {{Dereference of null pointer}}
338d7c8a4dSAnna Zaks }
348d7c8a4dSAnna Zaks 
test04(int * p)358d7c8a4dSAnna Zaks int test04(int *p) {
368d7c8a4dSAnna Zaks   if (p)
378d7c8a4dSAnna Zaks     ;
388d7c8a4dSAnna Zaks   idc(p);
398d7c8a4dSAnna Zaks   return deref04(p);
408d7c8a4dSAnna Zaks }
418d7c8a4dSAnna Zaks 
test11(int * q,int * x)428d7c8a4dSAnna Zaks int test11(int *q, int *x) {
438d7c8a4dSAnna Zaks 	int *p = q;
448d7c8a4dSAnna Zaks 	if (q)
458d7c8a4dSAnna Zaks 		;
468d7c8a4dSAnna Zaks 	if (x)
478d7c8a4dSAnna Zaks 		;
488d7c8a4dSAnna Zaks 	return *p; // expected-warning{{Dereference of null pointer}}
498d7c8a4dSAnna Zaks }
508d7c8a4dSAnna Zaks 
test12(int * q)518d7c8a4dSAnna Zaks int test12(int *q) {
528d7c8a4dSAnna Zaks 	int *p = q;
538d7c8a4dSAnna Zaks 	idc(q);
548d7c8a4dSAnna Zaks 	return *p;
558d7c8a4dSAnna Zaks }
568d7c8a4dSAnna Zaks 
test13(int * q)578d7c8a4dSAnna Zaks int test13(int *q) {
588d7c8a4dSAnna Zaks 	int *p = q;
598d7c8a4dSAnna Zaks 	idc(p);
608d7c8a4dSAnna Zaks 	return *p;
618d7c8a4dSAnna Zaks }
628d7c8a4dSAnna Zaks 
test21(int * q,int * x)638d7c8a4dSAnna Zaks int test21(int *q, int *x) {
648d7c8a4dSAnna Zaks 	if (q)
658d7c8a4dSAnna Zaks 		;
668d7c8a4dSAnna Zaks 	if (x)
678d7c8a4dSAnna Zaks 		;
688d7c8a4dSAnna Zaks 	int *p = q;
698d7c8a4dSAnna Zaks 	return *p; // expected-warning{{Dereference of null pointer}}
708d7c8a4dSAnna Zaks }
718d7c8a4dSAnna Zaks 
test22(int * q,int * x)728d7c8a4dSAnna Zaks int test22(int *q, int *x) {
738d7c8a4dSAnna Zaks   idc(q);
748d7c8a4dSAnna Zaks 	if (x)
758d7c8a4dSAnna Zaks 		;
768d7c8a4dSAnna Zaks 	int *p = q;
778d7c8a4dSAnna Zaks 	return *p;
788d7c8a4dSAnna Zaks }
798d7c8a4dSAnna Zaks 
test23(int * q,int * x)808d7c8a4dSAnna Zaks int test23(int *q, int *x) {
818d7c8a4dSAnna Zaks   idc(q);
828d7c8a4dSAnna Zaks 	if (x)
838d7c8a4dSAnna Zaks 		;
848d7c8a4dSAnna Zaks 	int *p = q;
858d7c8a4dSAnna Zaks   if (!p)
868d7c8a4dSAnna Zaks     ;
878d7c8a4dSAnna Zaks 	return *p; // False negative
888d7c8a4dSAnna Zaks }
898d7c8a4dSAnna Zaks 
use(char * p)908d7c8a4dSAnna Zaks void use(char *p) {
918d7c8a4dSAnna Zaks   if (!p)
928d7c8a4dSAnna Zaks     return;
938d7c8a4dSAnna Zaks   p[0] = 'a';
948d7c8a4dSAnna Zaks }
958d7c8a4dSAnna Zaks 
test24(char * buffer)968d7c8a4dSAnna Zaks void test24(char *buffer) {
978d7c8a4dSAnna Zaks   use(buffer);
988d7c8a4dSAnna Zaks   buffer[1] = 'b';
998d7c8a4dSAnna Zaks }
1006c0c47edSAnna Zaks 
1016c0c47edSAnna Zaks // Ensure idc works on pointers with constant offset.
idcchar(const char * s2)1026c0c47edSAnna Zaks void idcchar(const char *s2) {
1036c0c47edSAnna Zaks   if(s2)
1046c0c47edSAnna Zaks     ;
1056c0c47edSAnna Zaks }
testConstantOffset(char * value)1066c0c47edSAnna Zaks void testConstantOffset(char *value) {
1076c0c47edSAnna Zaks   char *cursor = value + 5;
1086c0c47edSAnna Zaks   idcchar(cursor);
1096c0c47edSAnna Zaks   if (*cursor) {
1106c0c47edSAnna Zaks     cursor++;
1116c0c47edSAnna Zaks   }
1126c0c47edSAnna Zaks }
1135673b656SAnna Zaks 
1145673b656SAnna Zaks // Ensure idc works for integer zero values (ex: suppressed div by zero).
idcZero(int assume)1155673b656SAnna Zaks void idcZero(int assume) {
1165673b656SAnna Zaks   if (assume)
1175673b656SAnna Zaks     ;
1185673b656SAnna Zaks }
1195673b656SAnna Zaks 
idcTriggerZeroValue(int m)1205673b656SAnna Zaks int idcTriggerZeroValue(int m) {
1215673b656SAnna Zaks   idcZero(m);
1225673b656SAnna Zaks   return 5/m; // no-warning
1235673b656SAnna Zaks }
1245673b656SAnna Zaks 
idcTriggerZeroValueThroughCall(int i)1255673b656SAnna Zaks int idcTriggerZeroValueThroughCall(int i) {
1265673b656SAnna Zaks   return 5/i; // no-warning
1275673b656SAnna Zaks }
idcTrackZeroValueThroughCall(int x)1285673b656SAnna Zaks void idcTrackZeroValueThroughCall(int x) {
1295673b656SAnna Zaks   idcZero(x);
1305673b656SAnna Zaks   idcTriggerZeroValueThroughCall(x);
1315673b656SAnna Zaks }
1325673b656SAnna Zaks 
idcTriggerZeroThroughDoubleAssignemnt(int i)1335673b656SAnna Zaks int idcTriggerZeroThroughDoubleAssignemnt(int i) {
1345673b656SAnna Zaks   return 5/i; // no-warning
1355673b656SAnna Zaks }
idcTrackZeroThroughDoubleAssignemnt(int x)1365673b656SAnna Zaks void idcTrackZeroThroughDoubleAssignemnt(int x) {
1375673b656SAnna Zaks   idcZero(x);
1385673b656SAnna Zaks   int y = x;
1395673b656SAnna Zaks   int z = y;
1405673b656SAnna Zaks   idcTriggerZeroValueThroughCall(z);
1415673b656SAnna Zaks }
14237de8888SArtem Dergachev 
14337de8888SArtem Dergachev struct S {
14437de8888SArtem Dergachev   int f1;
14537de8888SArtem Dergachev   int f2;
14637de8888SArtem Dergachev };
14737de8888SArtem Dergachev 
idcTrackZeroValueThroughUnaryPointerOperators(struct S * s)14837de8888SArtem Dergachev void idcTrackZeroValueThroughUnaryPointerOperators(struct S *s) {
14937de8888SArtem Dergachev   idc(s);
15037de8888SArtem Dergachev   *(&(s->f1)) = 7; // no-warning
15137de8888SArtem Dergachev }
15237de8888SArtem Dergachev 
idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S * s)15337de8888SArtem Dergachev void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset1(struct S *s) {
15437de8888SArtem Dergachev   idc(s);
15537de8888SArtem Dergachev   int *x = &(s->f2);
15637de8888SArtem Dergachev   *x = 7; // no-warning
15737de8888SArtem Dergachev }
15837de8888SArtem Dergachev 
idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S * s)15937de8888SArtem Dergachev void idcTrackZeroValueThroughUnaryPointerOperatorsWithOffset2(struct S *s) {
16037de8888SArtem Dergachev   idc(s);
16137de8888SArtem Dergachev   int *x = &(s->f2) - 1;
162*95f9a68bSArtem Dergachev   *x = 7; // no-warning
16337de8888SArtem Dergachev }
16437de8888SArtem Dergachev 
idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S * s)16537de8888SArtem Dergachev void idcTrackZeroValueThroughUnaryPointerOperatorsWithAssignment(struct S *s) {
16637de8888SArtem Dergachev   idc(s);
16737de8888SArtem Dergachev   int *x = &(s->f1);
16837de8888SArtem Dergachev   *x = 7; // no-warning
16937de8888SArtem Dergachev }
17037de8888SArtem Dergachev 
idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignment(struct S * s)1718c800615SArtem Dergachev void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignment(struct S *s) {
1728c800615SArtem Dergachev   idc(s);
1738c800615SArtem Dergachev   int *x = &*&(s->f1);
1748c800615SArtem Dergachev   *x = 7; // no-warning
1758c800615SArtem Dergachev }
1768c800615SArtem Dergachev 
idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignmentAndUnaryIncrement(struct S * s)1778c800615SArtem Dergachev void idcTrackZeroValueThroughManyUnaryPointerOperatorsWithAssignmentAndUnaryIncrement(struct S *s) {
1788c800615SArtem Dergachev   idc(s);
1798c800615SArtem Dergachev   int *x = &*&((++s)->f1);
1808c800615SArtem Dergachev   *x = 7; // no-warning
1818c800615SArtem Dergachev }
1828c800615SArtem Dergachev 
18337de8888SArtem Dergachev 
18437de8888SArtem Dergachev struct S2 {
18537de8888SArtem Dergachev   int a[1];
18637de8888SArtem Dergachev };
18737de8888SArtem Dergachev 
idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 * s)18837de8888SArtem Dergachev void idcTrackZeroValueThroughUnaryPointerOperatorsWithArrayField(struct S2 *s) {
18937de8888SArtem Dergachev   idc(s);
19037de8888SArtem Dergachev   *(&(s->a[0])) = 7; // no-warning
19137de8888SArtem Dergachev }
192fcad574cSArtem Dergachev 
idcTrackConstraintThroughSymbolicRegion(int ** x)193fcad574cSArtem Dergachev void idcTrackConstraintThroughSymbolicRegion(int **x) {
194fcad574cSArtem Dergachev   idc(*x);
195fcad574cSArtem Dergachev   // FIXME: Should not warn.
196fcad574cSArtem Dergachev   **x = 7; // expected-warning{{Dereference of null pointer}}
197fcad574cSArtem Dergachev }
198fcad574cSArtem Dergachev 
idcTrackConstraintThroughSymbolicRegionAndParens(int ** x)199fee10106SArtem Dergachev void idcTrackConstraintThroughSymbolicRegionAndParens(int **x) {
200fee10106SArtem Dergachev   idc(*x);
201fee10106SArtem Dergachev   // FIXME: Should not warn.
202fee10106SArtem Dergachev   *(*x) = 7; // expected-warning{{Dereference of null pointer}}
203fee10106SArtem Dergachev }
204fee10106SArtem Dergachev 
idcPlainNull(int coin)205fcad574cSArtem Dergachev int *idcPlainNull(int coin) {
206fcad574cSArtem Dergachev   if (coin)
207fcad574cSArtem Dergachev     return 0;
208fcad574cSArtem Dergachev   static int X;
209fcad574cSArtem Dergachev   return &X;
210fcad574cSArtem Dergachev }
211fcad574cSArtem Dergachev 
idcTrackZeroValueThroughSymbolicRegion(int coin,int ** x)212fcad574cSArtem Dergachev void idcTrackZeroValueThroughSymbolicRegion(int coin, int **x) {
213fcad574cSArtem Dergachev   *x = idcPlainNull(coin);
214fcad574cSArtem Dergachev   **x = 7; // no-warning
215fcad574cSArtem Dergachev }
216fee10106SArtem Dergachev 
idcTrackZeroValueThroughSymbolicRegionAndParens(int coin,int ** x)217fee10106SArtem Dergachev void idcTrackZeroValueThroughSymbolicRegionAndParens(int coin, int **x) {
218fee10106SArtem Dergachev   *x = idcPlainNull(coin);
219fee10106SArtem Dergachev   *(*x) = 7; // no-warning
220fee10106SArtem Dergachev }
221fee10106SArtem Dergachev 
222fee10106SArtem Dergachev struct WithInt {
223fee10106SArtem Dergachev   int i;
224fee10106SArtem Dergachev };
225fee10106SArtem Dergachev 
226fee10106SArtem Dergachev struct WithArray {
227fee10106SArtem Dergachev   struct WithInt arr[1];
228fee10106SArtem Dergachev };
229fee10106SArtem Dergachev 
idcPlainNullWithArray(int coin)230fee10106SArtem Dergachev struct WithArray *idcPlainNullWithArray(int coin) {
231fee10106SArtem Dergachev   if (coin)
232fee10106SArtem Dergachev     return 0;
233fee10106SArtem Dergachev   static struct WithArray S;
234fee10106SArtem Dergachev   return &S;
235fee10106SArtem Dergachev }
236fee10106SArtem Dergachev 
idcTrackZeroValueThroughSymbolicRegionWithArray(int coin,struct WithArray ** s)237fee10106SArtem Dergachev void idcTrackZeroValueThroughSymbolicRegionWithArray(int coin, struct WithArray **s) {
238fee10106SArtem Dergachev   *s = idcPlainNullWithArray(coin);
239fee10106SArtem Dergachev   (*s)->arr[0].i = 1; // no-warning
240fee10106SArtem Dergachev   // Same thing.
241fee10106SArtem Dergachev   (*s)->arr->i = 1; // no-warning
242fee10106SArtem Dergachev }
243