[RISCV] Simplify usage of SplatPat_simm5_plus1. NFC (#125340)
[llvm-project.git] / clang / test / Analysis / fread.c
blob8dc998ea1e899d0a5d357941d577a7bf61f5f7aa
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -triple x86_64-linux-gnu \
3 // RUN: -analyzer-checker=core,unix.Stream,optin.taint \
4 // RUN: -analyzer-checker=debug.ExprInspection
6 #include "Inputs/system-header-simulator-for-simple-stream.h"
8 #define EOF (-1)
10 void clang_analyzer_dump(int);
11 void clang_analyzer_dump_char(char);
12 void clang_analyzer_isTainted(int);
13 void clang_analyzer_warnIfReached(void);
15 // A stream is only tracked by StreamChecker if it results from a call to "fopen".
16 // Otherwise, there is no specific modelling of "fread".
17 void untracked_stream(FILE *fp) {
18 char c;
19 if (1 == fread(&c, 1, 1, fp)) {
20 char p = c; // Unknown value but not garbage and not modeled by checker.
21 } else {
22 char p = c; // Possibly indeterminate value but not modeled by checker.
26 void fgetc_props_taint(void) {
27 FILE *fp = fopen("/home/test", "rb+");
28 if (fp) {
29 int c = fgetc(fp); // c is tainted.
30 if (c != EOF) {
31 clang_analyzer_isTainted(c); // expected-warning{{YES}}
33 fclose(fp);
37 void fread_props_taint(void) {
38 FILE *fp = fopen("/home/test", "rb+");
39 if (fp) {
40 char buffer[10];
41 int c = fread(buffer, 1, 10, fp); // c is tainted.
42 if (c != 10) {
43 // If the read failed, then the number of bytes successfully read should be tainted.
44 clang_analyzer_isTainted(c); // expected-warning{{YES}}
46 fclose(fp);
50 void read_one_byte1(void) {
51 FILE *fp = fopen("/home/test", "rb+");
52 if (fp) {
53 char c;
54 if (1 == fread(&c, 1, 1, fp)) {
55 char p = c; // Unknown value but not garbage.
56 clang_analyzer_isTainted(p); // expected-warning{{YES}}
57 } else {
58 char p = c; // Possibly indeterminate value but not modeled by checker.
59 clang_analyzer_isTainted(p); // expected-warning{{YES}}
61 fclose(fp);
65 void read_one_byte2(char *buffer) {
66 FILE *fp = fopen("/home/test", "rb+");
67 if (fp) {
68 if (1 == fread(buffer, 1, 1, fp)) {
69 char p = buffer[0]; // Unknown value but not garbage.
70 clang_analyzer_isTainted(p); // expected-warning{{YES}}
71 } else {
72 char p = buffer[0]; // Possibly indeterminate value but not modeled by checker.
73 clang_analyzer_isTainted(p); // expected-warning{{YES}}
75 fclose(fp);
79 void read_one_byte3(char *buffer) {
80 buffer[1] = 10;
81 FILE *fp = fopen("/home/test", "rb+");
82 if (fp) {
83 // buffer[1] is not mutated by fread and remains not tainted.
84 fread(buffer, 1, 1, fp);
85 char p = buffer[1];
86 clang_analyzer_isTainted(p); // expected-warning{{NO}}
87 clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}}
88 fclose(fp);
92 void read_many_bytes(char *buffer) {
93 FILE *fp = fopen("/home/test", "rb+");
94 if (fp) {
95 if (42 == fread(buffer, 1, 42, fp)) {
96 char p = buffer[0]; // Unknown value but not garbage.
97 clang_analyzer_isTainted(p); // expected-warning{{YES}}
98 } else {
99 char p = buffer[0]; // Possibly indeterminate value but not modeled.
100 clang_analyzer_isTainted(p); // expected-warning{{YES}}
102 fclose(fp);
106 void random_access_read1(int index) {
107 FILE *fp = fopen("/home/test", "rb+");
108 if (fp) {
109 long c[4];
110 int success = 2 == fread(c + 1, sizeof(long), 2, fp);
112 switch (index) {
113 case 0:
114 // c[0] is not mutated by fread.
115 if (success) {
116 char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact.
117 } else {
118 char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact.
120 break;
122 case 1:
123 if (success) {
124 // Unknown value but not garbage.
125 clang_analyzer_isTainted(c[1]); // expected-warning {{YES}}
126 clang_analyzer_dump(c[1]); // expected-warning {{conj_}}
127 } else {
128 // Possibly indeterminate value but not modeled.
129 clang_analyzer_isTainted(c[1]); // expected-warning {{YES}}
130 clang_analyzer_dump(c[1]); // expected-warning {{conj_}}
132 break;
134 case 2:
135 if (success) {
136 long p = c[2]; // Unknown value but not garbage.
137 // FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp.
138 clang_analyzer_isTainted(c[2]); // expected-warning {{NO}}
139 clang_analyzer_dump(c[2]); // expected-warning {{conj_}}
140 } else {
141 // Possibly indeterminate value but not modeled.
142 clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above.
143 clang_analyzer_dump(c[2]); // expected-warning {{conj_}}
145 break;
147 case 3:
148 // c[3] is not mutated by fread.
149 if (success) {
150 long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}}
151 } else {
152 long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}}
154 break;
157 fclose(fp);
161 void random_access_read2(int b) {
162 FILE *fp = fopen("/home/test", "rb+");
163 if (fp) {
164 int buffer[10];
165 int *ptr = buffer + 2;
166 if (5 == fread(ptr - 1, sizeof(int), 5, fp)) {
167 if (b) {
168 int p = buffer[1]; // Unknown value but not garbage.
169 clang_analyzer_isTainted(p); // expected-warning {{YES}}
170 clang_analyzer_dump(p); // expected-warning {{conj_}}
171 } else {
172 int p = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}}
174 } else {
175 int p = buffer[0]; // expected-warning {{Assigned value is garbage or undefined}}
177 fclose(fp);
181 void random_access_read_symbolic_count(size_t count) {
182 // Cover a case that used to crash (symbolic count).
183 if (count > 2)
184 return;
186 FILE *fp = fopen("/home/test", "rb+");
187 if (fp) {
188 long c[4];
189 fread(c + 1, sizeof(long), count, fp);
191 // c[0] and c[3] are never mutated by fread, but because "count" is a symbolic value, the checker doesn't know that.
192 long p = c[0];
193 clang_analyzer_isTainted(p); // expected-warning {{NO}}
194 clang_analyzer_dump(p); // expected-warning {{derived_}}
196 p = c[3];
197 clang_analyzer_isTainted(p); // expected-warning {{NO}}
198 clang_analyzer_dump(p); // expected-warning {{derived_}}
200 p = c[1];
201 clang_analyzer_isTainted(p); // expected-warning {{YES}}
202 clang_analyzer_dump(p); // expected-warning {{derived_}}
204 fclose(fp);
208 void dynamic_random_access_read(int startIndex) {
209 FILE *fp = fopen("/home/test", "rb+");
210 if (fp) {
211 long buffer[10];
212 // Cannot reason about index.
213 size_t res = fread(buffer + startIndex, sizeof(long), 5, fp);
214 long *p = &buffer[startIndex];
215 long v = 0;
217 // If all 5 elements were successfully read, then all 5 elements should be tainted and considered initialized.
218 if (5 == res) {
219 // FIXME: These should be tainted.
220 clang_analyzer_isTainted((v = p[0])); // expected-warning {{NO}}
221 clang_analyzer_isTainted((v = p[1])); // expected-warning {{NO}}
222 clang_analyzer_isTainted((v = p[2])); // expected-warning {{NO}}
223 clang_analyzer_isTainted((v = p[3])); // expected-warning {{NO}}
224 clang_analyzer_isTainted((v = p[4])); // expected-warning {{NO}}
225 clang_analyzer_dump((v = p[0])); // expected-warning {{conj_}} ok
226 clang_analyzer_dump((v = p[1])); // expected-warning {{conj_}} ok
227 clang_analyzer_dump((v = p[2])); // expected-warning {{conj_}} ok
228 clang_analyzer_dump((v = p[3])); // expected-warning {{conj_}} ok
229 clang_analyzer_dump((v = p[4])); // expected-warning {{conj_}} ok
230 clang_analyzer_dump((v = p[5])); // expected-warning {{conj_}} FIXME: This should raise an uninit read.
231 } else if (res == 4) {
232 // If only the first 4 elements were successfully read,
233 // then only the first 4 elements should be tainted and considered initialized.
234 // FIXME: These should be tainted.
235 clang_analyzer_isTainted((v = p[0])); // expected-warning {{NO}}
236 clang_analyzer_isTainted((v = p[1])); // expected-warning {{NO}}
237 clang_analyzer_isTainted((v = p[2])); // expected-warning {{NO}}
238 clang_analyzer_isTainted((v = p[3])); // expected-warning {{NO}}
239 clang_analyzer_dump((v = p[0])); // expected-warning {{conj_}} ok
240 clang_analyzer_dump((v = p[1])); // expected-warning {{conj_}} ok
241 clang_analyzer_dump((v = p[2])); // expected-warning {{conj_}} ok
242 clang_analyzer_dump((v = p[3])); // expected-warning {{conj_}} ok
243 clang_analyzer_dump((v = p[4])); // expected-warning {{conj_}} FIXME: This should raise an uninit read.
244 } else {
245 // Neither 5, or 4 elements were successfully read, so we must have read from 0 up to 3 elements.
246 // FIXME: These should be tainted.
247 clang_analyzer_isTainted((v = p[0])); // expected-warning {{NO}}
248 clang_analyzer_isTainted((v = p[1])); // expected-warning {{NO}}
249 clang_analyzer_isTainted((v = p[2])); // expected-warning {{NO}}
250 clang_analyzer_dump((v = p[0])); // expected-warning {{conj_}} ok
251 clang_analyzer_dump((v = p[1])); // expected-warning {{conj_}} ok
252 clang_analyzer_dump((v = p[2])); // expected-warning {{conj_}} ok
253 clang_analyzer_dump((v = p[3])); // expected-warning {{conj_}} FIXME: This should raise an uninit read.
255 fclose(fp);
259 struct S {
260 int a;
261 long b;
264 void compound_read1(void) {
265 FILE *fp = fopen("/home/test", "rb+");
266 if (fp) {
267 struct S s; // s.a is not touched by fread.
268 if (1 == fread(&s.b, sizeof(s.b), 1, fp)) {
269 long p = s.b;
270 clang_analyzer_isTainted(p); // expected-warning {{YES}}
271 clang_analyzer_dump(p); // expected-warning {{conj_}}
272 } else {
273 long p = s.b;
274 clang_analyzer_isTainted(p); // expected-warning {{YES}}
275 clang_analyzer_dump(p); // expected-warning {{conj_}}
277 fclose(fp);
281 void compound_read2(void) {
282 FILE *fp = fopen("/home/test", "rb+");
283 if (fp) {
284 struct S s; // s.a is not touched by fread.
285 if (1 == fread(&s.b, sizeof(s.b), 1, fp)) {
286 long p = s.a; // expected-warning {{Assigned value is garbage or undefined}}
287 } else {
288 long p = s.a; // expected-warning {{Assigned value is garbage or undefined}}
290 fclose(fp);
294 void var_read(void) {
295 FILE *fp = fopen("/home/test", "rb+");
296 if (fp) {
297 int a, b; // 'a' is not touched by fread.
298 if (1 == fread(&b, sizeof(b), 1, fp)) {
299 long p = a; // expected-warning{{Assigned value is garbage or undefined}}
300 } else {
301 long p = a; // expected-warning{{Assigned value is garbage or undefined}}
303 fclose(fp);
307 // When reading a lot of data, invalidating all elements is too time-consuming.
308 // Instead, the knowledge of the whole array is lost.
309 #define MaxInvalidatedElementRegion 64 // See StreamChecker::evalFreadFwrite in StreamChecker.cpp.
310 #define PastMaxComplexity MaxInvalidatedElementRegion + 1
311 void test_large_read(void) {
312 int buffer[PastMaxComplexity + 1];
313 buffer[PastMaxComplexity] = 42;
314 FILE *fp = fopen("/home/test", "rb+");
315 if (fp) {
316 if (buffer[PastMaxComplexity] != 42) {
317 clang_analyzer_warnIfReached(); // Unreachable.
319 if (1 == fread(buffer, sizeof(int), PastMaxComplexity, fp)) {
320 if (buffer[PastMaxComplexity] != 42) {
321 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
324 fclose(fp);
328 void test_small_read(void) {
329 int buffer[10];
330 buffer[5] = 42;
331 FILE *fp = fopen("/home/test", "rb+");
332 if (fp) {
333 clang_analyzer_dump(buffer[5]); // expected-warning{{42 S32b}}
334 if (1 == fread(buffer, sizeof(int), 5, fp)) {
335 clang_analyzer_dump(buffer[5]); // expected-warning{{42 S32b}}
337 fclose(fp);
341 void test_partial_elements_read(void) {
342 clang_analyzer_dump(sizeof(int)); // expected-warning {{4 S32b}}
344 int buffer[100];
345 buffer[0] = 1;
346 buffer[1] = 2;
347 buffer[2] = 3;
348 buffer[3] = 4;
349 buffer[4] = 5;
350 buffer[5] = 6;
351 FILE *fp = fopen("/home/test", "rb+");
352 if (fp) {
353 // 3*5: 15 bytes read; which is not exactly 4 integers, but we still invalidate the first 4 ints.
354 if (5 == fread(buffer + 1, 3, 5, fp)) {
355 clang_analyzer_dump(buffer[0]); // expected-warning{{1 S32b}}
356 clang_analyzer_dump(buffer[1]); // expected-warning{{conj_}}
357 clang_analyzer_dump(buffer[2]); // expected-warning{{conj_}}
358 clang_analyzer_dump(buffer[3]); // expected-warning{{conj_}}
359 clang_analyzer_dump(buffer[4]); // expected-warning{{conj_}}
360 clang_analyzer_dump(buffer[5]); // expected-warning{{6 S32b}}
362 char *c = (char*)buffer;
363 clang_analyzer_dump(c[4+12]); // expected-warning{{conj_}} 16th byte of buffer, which is the beginning of the 4th 'int' in the buffer.
365 // FIXME: The store should have returned a partial binding for the 17th byte of the buffer, which is the 2nd byte of the previous int.
366 // This byte should have been initialized by the 'fread' earlier. However, the Store lies to us and says it's uninitialized.
367 clang_analyzer_dump(c[4+13]); // expected-warning{{1st function call argument is an uninitialized value}} should be initialized.
368 clang_analyzer_dump(c[4+16]); // This should be the first byte that 'fread' leaves uninitialized. This should raise the uninit read diag.
369 } else {
370 clang_analyzer_dump(buffer[0]); // expected-warning{{1 S32b}} ok
371 clang_analyzer_dump(buffer[1]); // expected-warning{{conj_}} ok
372 clang_analyzer_dump(buffer[2]); // expected-warning{{conj_}} ok
373 clang_analyzer_dump(buffer[3]); // expected-warning{{conj_}} ok
374 clang_analyzer_dump(buffer[4]); // expected-warning{{conj_}} ok, but an uninit warning would be also fine.
375 clang_analyzer_dump(buffer[5]); // expected-warning{{6 S32b}} ok
376 clang_analyzer_dump(buffer[6]); // expected-warning{{1st function call argument is an uninitialized value}} ok
378 fclose(fp);
382 void test_whole_elements_read(void) {
383 clang_analyzer_dump(sizeof(int)); // expected-warning {{4 S32b}}
385 int buffer[100];
386 buffer[0] = 1;
387 buffer[15] = 2;
388 buffer[16] = 3;
389 FILE *fp = fopen("/home/test", "rb+");
390 if (fp) {
391 // 3*20: 60 bytes read; which is basically 15 integers.
392 if (20 == fread(buffer + 1, 3, 20, fp)) {
393 clang_analyzer_dump(buffer[0]); // expected-warning{{1 S32b}}
394 clang_analyzer_dump(buffer[15]); // expected-warning{{conj_}}
395 clang_analyzer_dump(buffer[16]); // expected-warning{{3 S32b}}
396 clang_analyzer_dump(buffer[17]); // expected-warning{{1st function call argument is an uninitialized value}}
397 } else {
398 clang_analyzer_dump(buffer[0]); // expected-warning{{1 S32b}}
399 clang_analyzer_dump(buffer[15]); // expected-warning{{conj_}}
400 clang_analyzer_dump(buffer[16]); // expected-warning{{3 S32b}}
401 clang_analyzer_dump(buffer[17]); // expected-warning{{1st function call argument is an uninitialized value}}
403 fclose(fp);
407 void test_unaligned_start_read(void) {
408 clang_analyzer_dump(sizeof(int)); // expected-warning {{4 S32b}}
410 int buffer[100];
411 buffer[0] = 3;
412 buffer[1] = 4;
413 buffer[2] = 5;
414 char *asChar = (char*)buffer;
416 FILE *fp = fopen("/home/test", "rb+");
417 if (fp) {
418 // We have an 'int' binding at offset 0 of value 3.
419 // We read 4 bytes at byte offset: 1,2,3,4.
420 if (4 == fread(asChar + 1, 1, 4, fp)) {
421 clang_analyzer_dump(buffer[0]); // expected-warning{{3 S32b}} FIXME: The int binding should have been partially overwritten by the read call. This definitely should not be 3.
422 clang_analyzer_dump(buffer[1]); // expected-warning{{conj_}}
423 clang_analyzer_dump(buffer[2]); // expected-warning{{5 S32b}}
425 clang_analyzer_dump_char(asChar[0]); // expected-warning{{3 S8b}} This is technically true assuming x86 (little-endian) architecture.
426 clang_analyzer_dump_char(asChar[1]); // expected-warning{{conj_}} 1
427 clang_analyzer_dump_char(asChar[2]); // expected-warning{{conj_}} 2
428 clang_analyzer_dump_char(asChar[3]); // expected-warning{{conj_}} 3
429 clang_analyzer_dump_char(asChar[4]); // expected-warning{{conj_}} 4
430 clang_analyzer_dump_char(asChar[5]); // expected-warning{{1st function call argument is an uninitialized value}}
431 } else {
432 clang_analyzer_dump(buffer[0]); // expected-warning{{3 S32b}} FIXME: The int binding should have been partially overwritten by the read call. This definitely should not be 3.
433 clang_analyzer_dump(buffer[1]); // expected-warning{{conj_}}
434 clang_analyzer_dump(buffer[2]); // expected-warning{{5 S32b}}
436 clang_analyzer_dump_char(asChar[0]); // expected-warning{{3 S8b}} This is technically true assuming x86 (little-endian) architecture.
437 clang_analyzer_dump_char(asChar[1]); // expected-warning{{conj_}} 1
438 clang_analyzer_dump_char(asChar[2]); // expected-warning{{conj_}} 2
439 clang_analyzer_dump_char(asChar[3]); // expected-warning{{conj_}} 3
440 clang_analyzer_dump_char(asChar[4]); // expected-warning{{conj_}} 4
441 clang_analyzer_dump_char(asChar[5]); // expected-warning{{1st function call argument is an uninitialized value}}
443 fclose(fp);
447 void no_crash_if_count_is_negative(long l, long r, unsigned char *buffer) {
448 FILE *fp = fopen("path", "r");
449 if (fp) {
450 if (l * r == -1) {
451 fread(buffer, 1, l * r, fp); // no-crash
453 fclose(fp);
457 void no_crash_if_size_is_negative(long l, long r, unsigned char *buffer) {
458 FILE *fp = fopen("path", "r");
459 if (fp) {
460 if (l * r == -1) {
461 fread(buffer, l * r, 1, fp); // no-crash
463 fclose(fp);
467 void no_crash_if_size_and_count_are_negative(long l, long r, unsigned char *buffer) {
468 FILE *fp = fopen("path", "r");
469 if (fp) {
470 if (l * r == -1) {
471 fread(buffer, l * r, l * r, fp); // no-crash
473 fclose(fp);