xref: /llvm-project/clang/test/Analysis/stream-invalidate.c (revision 09f160c6298255f520b379b88161fbd1c365b308)
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=unix.Stream \
4 // RUN: -analyzer-checker=debug.ExprInspection
5 
6 #include "Inputs/system-header-simulator.h"
7 #include "Inputs/system-header-simulator-for-valist.h"
8 
9 void clang_analyzer_eval(int);
10 void clang_analyzer_dump(int);
11 
test_fread(void)12 void test_fread(void) {
13   FILE *F = fopen("file", "r+");
14   if (!F)
15     return;
16 
17   char Buf[3] = {10, 10, 10};
18   fread(Buf, 1, 3, F);
19   // The check applies to success and failure.
20   clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10.
21   clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}}
22   if (feof(F)) {
23     char Buf1[3] = {10, 10, 10};
24     fread(Buf1, 1, 3, F); // expected-warning {{is in EOF state}}
25     clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}}
26     clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}}
27   }
28 
29   fclose(F);
30 }
31 
test_fwrite(void)32 void test_fwrite(void) {
33   FILE *F = fopen("file", "r+");
34   if (!F)
35     return;
36 
37   char Buf[3] = {10, 10, 10};
38   fwrite(Buf, 1, 3, F);
39   // The check applies to success and failure.
40   clang_analyzer_dump(Buf[0]); // expected-warning {{10 S32b}}
41   clang_analyzer_dump(Buf[2]); // expected-warning {{10 S32b}}
42 
43   fclose(F);
44 }
45 
test_fgets()46 void test_fgets() {
47   FILE *F = tmpfile();
48   if (!F)
49     return;
50 
51   char Buf[3] = {10, 10, 10};
52   fgets(Buf, 3, F);
53   // The check applies to success and failure.
54   clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10.
55   clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}}
56   if (feof(F)) {
57     char Buf1[3] = {10, 10, 10};
58     fgets(Buf1, 3, F); // expected-warning {{is in EOF state}}
59     clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}}
60     clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}}
61   }
62 
63   fclose(F);
64 }
65 
test_fputs()66 void test_fputs() {
67   FILE *F = tmpfile();
68   if (!F)
69     return;
70 
71   char *Buf = "aaa";
72   fputs(Buf, F);
73   // The check applies to success and failure.
74   clang_analyzer_dump(Buf[0]); // expected-warning {{97 S32b}}
75   clang_analyzer_dump(Buf[2]); // expected-warning {{97 S32b}}
76   clang_analyzer_dump(Buf[3]); // expected-warning {{0 S32b}}
77 
78   fclose(F);
79 }
80 
test_fscanf()81 void test_fscanf() {
82   FILE *F = tmpfile();
83   if (!F)
84     return;
85 
86   int a = 1;
87   unsigned b;
88   int Ret = fscanf(F, "%d %u", &a, &b);
89   if (Ret == 0) {
90     clang_analyzer_dump(a); // expected-warning {{conj_$}}
91     // FIXME: should be {{1 S32b}}.
92     clang_analyzer_dump(b); // expected-warning {{conj_$}}
93     // FIXME: should be {{uninitialized value}}.
94   } else if (Ret == 1) {
95     clang_analyzer_dump(a); // expected-warning {{conj_$}}
96     clang_analyzer_dump(b); // expected-warning {{conj_$}}
97     // FIXME: should be {{uninitialized value}}.
98   } else if (Ret >= 2) {
99     clang_analyzer_dump(a); // expected-warning {{conj_$}}
100     clang_analyzer_dump(b); // expected-warning {{conj_$}}
101     clang_analyzer_eval(Ret == 2); // expected-warning {{FALSE}} expected-warning {{TRUE}}
102     // FIXME: should be only TRUE.
103   } else {
104     clang_analyzer_dump(a); // expected-warning {{1 S32b}}
105     clang_analyzer_dump(b); // expected-warning {{uninitialized value}}
106   }
107 
108   fclose(F);
109 }
110 
test_getdelim(char * P,size_t Sz)111 void test_getdelim(char *P, size_t Sz) {
112   FILE *F = tmpfile();
113   if (!F)
114     return;
115 
116   char *P1 = P;
117   size_t Sz1 = Sz;
118   ssize_t Ret = getdelim(&P, &Sz, '\t', F);
119   if (Ret < 0) {
120     clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \
121                                   // expected-warning {{TRUE}}
122     clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \
123                                     // expected-warning {{TRUE}}
124   } else {
125     clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \
126                                   // expected-warning {{TRUE}}
127     clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \
128                                     // expected-warning {{TRUE}}
129   }
130 
131   fclose(F);
132 }
133 
test_fgetpos()134 void test_fgetpos() {
135   FILE *F = tmpfile();
136   if (!F)
137     return;
138 
139   fpos_t Pos = 1;
140   int Ret = fgetpos(F, &Pos);
141   if (Ret == 0) {
142     clang_analyzer_dump(Pos); // expected-warning {{conj_$}}
143   } else {
144     clang_analyzer_dump(Pos); // expected-warning {{1 S32b}}
145   }
146 
147   fclose(F);
148 }
149 
test_fprintf()150 void test_fprintf() {
151   FILE *F1 = tmpfile();
152   if (!F1)
153     return;
154 
155   unsigned a = 42;
156   char *output = "HELLO";
157   int r = fprintf(F1, "%s\t%u\n", output, a);
158   // fprintf does not invalidate any of its input
159   // 69 is ascii for 'E'
160   clang_analyzer_dump(a); // expected-warning {{42 S32b}}
161   clang_analyzer_dump(output[1]); // expected-warning {{69 S32b}}
162   fclose(F1);
163 }
164 
test_vfscanf_inner(const char * fmt,...)165 int test_vfscanf_inner(const char *fmt, ...) {
166   FILE *F1 = tmpfile();
167   if (!F1)
168     return EOF;
169 
170   va_list ap;
171   va_start(ap, fmt);
172 
173   int r = vfscanf(F1, fmt, ap);
174 
175   fclose(F1);
176   va_end(ap);
177   return r;
178 }
179 
test_vfscanf()180 void test_vfscanf() {
181   int i = 42;
182   int j = 43;
183   int r = test_vfscanf_inner("%d", &i);
184   if (r != EOF) {
185     // i gets invalidated by the call to test_vfscanf_inner, not by vfscanf.
186     clang_analyzer_dump(i); // expected-warning {{conj_$}}
187     clang_analyzer_dump(j); // expected-warning {{43 S32b}}
188   }
189 }
190