[clang][NFC] simplify the unset check in `ParseLabeledStatement` (#117430)
[llvm-project.git] / clang / test / Analysis / stream.c
blob758b40cca49319a0579de71e2d0ef2ab79a8c835
1 // RUN: %clang_analyze_cc1 -triple=x86_64-pc-linux-gnu -analyzer-checker=core,unix.Stream,debug.ExprInspection \
2 // RUN: -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s
3 // RUN: %clang_analyze_cc1 -triple=armv8-none-linux-eabi -analyzer-checker=core,unix.Stream,debug.ExprInspection \
4 // RUN: -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s
5 // RUN: %clang_analyze_cc1 -triple=aarch64-linux-gnu -analyzer-checker=core,unix.Stream,debug.ExprInspection \
6 // RUN: -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s
7 // RUN: %clang_analyze_cc1 -triple=hexagon -analyzer-checker=core,unix.Stream,debug.ExprInspection \
8 // RUN: -analyzer-config eagerly-assume=false,unix.Stream:Pedantic=true -verify %s
10 #include "Inputs/system-header-simulator.h"
11 #include "Inputs/system-header-simulator-for-malloc.h"
12 #include "Inputs/system-header-simulator-for-valist.h"
14 void clang_analyzer_eval(int);
16 void check_fread(void) {
17 FILE *fp = tmpfile();
18 fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
19 fclose(fp);
22 void check_fwrite(void) {
23 FILE *fp = tmpfile();
24 fwrite(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
25 fclose(fp);
28 void check_fgetc(void) {
29 FILE *fp = tmpfile();
30 fgetc(fp); // expected-warning {{Stream pointer might be NULL}}
31 fclose(fp);
34 void check_fgets(void) {
35 FILE *fp = tmpfile();
36 char buf[256];
37 fgets(buf, sizeof(buf), fp); // expected-warning {{Stream pointer might be NULL}}
38 fclose(fp);
41 void check_fputc(void) {
42 FILE *fp = tmpfile();
43 fputc('A', fp); // expected-warning {{Stream pointer might be NULL}}
44 fclose(fp);
47 void check_fputs(void) {
48 FILE *fp = tmpfile();
49 fputs("ABC", fp); // expected-warning {{Stream pointer might be NULL}}
50 fclose(fp);
53 void check_fprintf(void) {
54 FILE *fp = tmpfile();
55 fprintf(fp, "ABC"); // expected-warning {{Stream pointer might be NULL}}
56 fclose(fp);
59 void check_fscanf(void) {
60 FILE *fp = tmpfile();
61 fscanf(fp, "ABC"); // expected-warning {{Stream pointer might be NULL}}
62 fclose(fp);
65 void check_ungetc(void) {
66 FILE *fp = tmpfile();
67 ungetc('A', fp); // expected-warning {{Stream pointer might be NULL}}
68 fclose(fp);
71 void check_fseek(void) {
72 FILE *fp = tmpfile();
73 fseek(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}
74 fclose(fp);
77 void check_fseeko(void) {
78 FILE *fp = tmpfile();
79 fseeko(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}
80 fclose(fp);
83 void check_ftell(void) {
84 FILE *fp = tmpfile();
85 ftell(fp); // expected-warning {{Stream pointer might be NULL}}
86 fclose(fp);
89 void check_ftello(void) {
90 FILE *fp = tmpfile();
91 ftello(fp); // expected-warning {{Stream pointer might be NULL}}
92 fclose(fp);
95 void check_rewind(void) {
96 FILE *fp = tmpfile();
97 rewind(fp); // expected-warning {{Stream pointer might be NULL}}
98 fclose(fp);
101 void check_fgetpos(void) {
102 FILE *fp = tmpfile();
103 fpos_t pos;
104 fgetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
105 fclose(fp);
108 void check_fsetpos(void) {
109 FILE *fp = tmpfile();
110 fpos_t pos;
111 fsetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
112 fclose(fp);
115 void check_clearerr(void) {
116 FILE *fp = tmpfile();
117 clearerr(fp); // expected-warning {{Stream pointer might be NULL}}
118 fclose(fp);
121 void check_feof(void) {
122 FILE *fp = tmpfile();
123 feof(fp); // expected-warning {{Stream pointer might be NULL}}
124 fclose(fp);
127 void check_ferror(void) {
128 FILE *fp = tmpfile();
129 ferror(fp); // expected-warning {{Stream pointer might be NULL}}
130 fclose(fp);
133 void check_fileno(void) {
134 FILE *fp = tmpfile();
135 fileno(fp); // expected-warning {{Stream pointer might be NULL}}
136 fclose(fp);
139 void f_open(void) {
140 FILE *p = fopen("foo", "r");
141 char buf[1024];
142 fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL}}
143 fclose(p);
146 void f_dopen(int fd) {
147 FILE *F = fdopen(fd, "r");
148 char buf[1024];
149 fread(buf, 1, 1, F); // expected-warning {{Stream pointer might be NULL}}
150 fclose(F);
153 void f_vfprintf(int fd, va_list args) {
154 FILE *F = fdopen(fd, "r");
155 vfprintf(F, "%d", args); // expected-warning {{Stream pointer might be NULL}}
156 fclose(F);
159 void f_vfscanf(int fd, va_list args) {
160 FILE *F = fdopen(fd, "r");
161 vfscanf(F, "%u", args); // expected-warning {{Stream pointer might be NULL}}
162 fclose(F);
165 void f_seek(void) {
166 FILE *p = fopen("foo", "r");
167 if (!p)
168 return;
169 fseek(p, 1, SEEK_SET); // no-warning
170 fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
171 fclose(p);
174 void f_seeko(void) {
175 FILE *p = fopen("foo", "r");
176 if (!p)
177 return;
178 fseeko(p, 1, SEEK_SET); // no-warning
179 fseeko(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
180 fclose(p);
183 void f_double_close(void) {
184 FILE *p = fopen("foo", "r");
185 if (!p)
186 return;
187 fclose(p);
188 fclose(p); // expected-warning {{Use of a stream that might be already closed}}
191 void f_double_close_alias(void) {
192 FILE *p1 = fopen("foo", "r");
193 if (!p1)
194 return;
195 FILE *p2 = p1;
196 fclose(p1);
197 fclose(p2); // expected-warning {{Use of a stream that might be already closed}}
200 void f_use_after_close(void) {
201 FILE *p = fopen("foo", "r");
202 if (!p)
203 return;
204 fclose(p);
205 clearerr(p); // expected-warning {{Use of a stream that might be already closed}}
208 void f_open_after_close(void) {
209 FILE *p = fopen("foo", "r");
210 if (!p)
211 return;
212 fclose(p);
213 p = fopen("foo", "r");
214 if (!p)
215 return;
216 fclose(p);
219 void f_reopen_after_close(void) {
220 FILE *p = fopen("foo", "r");
221 if (!p)
222 return;
223 fclose(p);
224 // Allow reopen after close.
225 p = freopen("foo", "w", p);
226 if (!p)
227 return;
228 fclose(p);
231 void f_leak(int c) {
232 FILE *p = fopen("foo.c", "r");
233 if (!p)
234 return;
235 if(c)
236 return; // expected-warning {{Opened stream never closed. Potential resource leak}}
237 fclose(p);
240 FILE *f_null_checked(void) {
241 FILE *p = fopen("foo.c", "r");
242 if (p)
243 return p; // no-warning
244 else
245 return 0;
248 void pr7831(FILE *fp) {
249 fclose(fp); // no-warning
252 // PR 8081 - null pointer crash when 'whence' is not an integer constant
253 void pr8081(FILE *stream, long offset, int whence) {
254 fseek(stream, offset, whence);
257 void check_freopen_1(void) {
258 FILE *f1 = freopen("foo.c", "r", (FILE *)0); // expected-warning {{Stream pointer might be NULL}}
259 f1 = freopen(0, "w", (FILE *)0x123456); // Do not report this as error.
262 void check_freopen_2(void) {
263 FILE *f1 = fopen("foo.c", "r");
264 if (f1) {
265 FILE *f2 = freopen(0, "w", f1);
266 if (f2) {
267 // Check if f1 and f2 point to the same stream.
268 fclose(f1);
269 fclose(f2); // expected-warning {{Use of a stream that might be already closed}}
270 } else {
271 // Reopen failed.
272 // f1 is non-NULL but points to a possibly invalid stream.
273 rewind(f1); // expected-warning {{Stream might be invalid}}
274 // f2 is NULL but the previous error stops the checker.
275 rewind(f2);
280 void check_freopen_3(void) {
281 FILE *f1 = fopen("foo.c", "r");
282 if (f1) {
283 // Unchecked result of freopen.
284 // The f1 may be invalid after this call.
285 freopen(0, "w", f1);
286 rewind(f1); // expected-warning {{Stream might be invalid}}
287 fclose(f1);
291 extern FILE *GlobalF;
292 extern void takeFile(FILE *);
294 void check_escape1(void) {
295 FILE *F = tmpfile();
296 if (!F)
297 return;
298 fwrite("1", 1, 1, F); // may fail
299 GlobalF = F;
300 fwrite("1", 1, 1, F); // no warning
303 void check_escape2(void) {
304 FILE *F = tmpfile();
305 if (!F)
306 return;
307 fwrite("1", 1, 1, F); // may fail
308 takeFile(F);
309 fwrite("1", 1, 1, F); // no warning
312 void check_escape3(void) {
313 FILE *F = tmpfile();
314 if (!F)
315 return;
316 takeFile(F);
317 F = freopen(0, "w", F);
318 if (!F)
319 return;
320 fwrite("1", 1, 1, F); // may fail
321 fwrite("1", 1, 1, F); // no warning
324 void check_escape4(void) {
325 FILE *F = tmpfile();
326 if (!F)
327 return;
328 fwrite("1", 1, 1, F); // may fail
330 // no escape at a non-StreamChecker-handled system call
331 setbuf(F, "0");
333 fwrite("1", 1, 1, F); // expected-warning {{might be 'indeterminate'}}
334 fclose(F);
337 int Test;
338 _Noreturn void handle_error(void);
340 void check_leak_noreturn_1(void) {
341 FILE *F1 = tmpfile();
342 if (!F1)
343 return;
344 if (Test == 1) {
345 handle_error(); // no warning
347 rewind(F1);
348 } // expected-warning {{Opened stream never closed. Potential resource leak}}
350 // Check that "location uniqueing" works.
351 // This results in reporting only one occurence of resource leak for a stream.
352 void check_leak_noreturn_2(void) {
353 FILE *F1 = tmpfile();
354 if (!F1)
355 return;
356 if (Test == 1) {
357 return; // no warning
359 rewind(F1);
360 } // expected-warning {{Opened stream never closed. Potential resource leak}}
361 // FIXME: This warning should be placed at the `return` above.
362 // See https://reviews.llvm.org/D83120 about details.
364 void fflush_after_fclose(void) {
365 FILE *F = tmpfile();
366 int Ret;
367 fflush(NULL); // no-warning
368 if (!F)
369 return;
370 if ((Ret = fflush(F)) != 0)
371 clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
372 fclose(F);
373 fflush(F); // expected-warning {{Use of a stream that might be already closed}}
376 void fflush_on_open_failed_stream(void) {
377 FILE *F = tmpfile();
378 if (!F) {
379 fflush(F); // no-warning
380 return;
382 fclose(F);
385 void getline_null_file() {
386 char *buffer = NULL;
387 size_t n = 0;
388 getline(&buffer, &n, NULL); // expected-warning {{Stream pointer might be NULL}}
391 void getdelim_null_file() {
392 char *buffer = NULL;
393 size_t n = 0;
394 getdelim(&buffer, &n, '\n', NULL); // expected-warning {{Stream pointer might be NULL}}
397 void getline_buffer_on_error() {
398 FILE *file = fopen("file.txt", "r");
399 if (file == NULL) {
400 return;
403 char *line = NULL;
404 size_t len = 0;
405 if (getline(&line, &len, file) == -1) {
406 if (line[0] == '\0') {} // expected-warning {{The left operand of '==' is a garbage value}}
407 } else {
408 if (line[0] == '\0') {} // no warning
411 free(line);
412 fclose(file);
415 void getline_ret_value() {
416 FILE *file = fopen("file.txt", "r");
417 if (file == NULL) {
418 return;
421 size_t n = 0;
422 char *buffer = NULL;
423 ssize_t r = getline(&buffer, &n, file);
425 if (r > -1) {
426 // The return value does *not* include the terminating null byte.
427 // The buffer must be large enough to include it.
428 clang_analyzer_eval(n > r); // expected-warning{{TRUE}}
429 clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}}
432 fclose(file);
433 free(buffer);
437 void getline_buffer_size_negative() {
438 FILE *file = fopen("file.txt", "r");
439 if (file == NULL) {
440 return;
443 size_t n = -1;
444 clang_analyzer_eval((ssize_t)n >= 0); // expected-warning{{FALSE}}
445 char *buffer = NULL;
446 ssize_t r = getline(&buffer, &n, file);
448 if (r > -1) {
449 clang_analyzer_eval((ssize_t)n > r); // expected-warning{{TRUE}}
450 clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}}
453 free(buffer);
454 fclose(file);
457 void gh_93408_regression(void *buffer) {
458 FILE *f = fopen("/tmp/foo.txt", "r");
459 fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash
460 fclose(f);
463 typedef void VOID;
464 void gh_93408_regression_typedef(VOID *buffer) {
465 FILE *f = fopen("/tmp/foo.txt", "r");
466 fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash
467 fclose(f);
470 struct FAM {
471 int data;
472 int tail[];
475 struct FAM0 {
476 int data;
477 int tail[0];
480 void gh_93408_regression_FAM(struct FAM *p) {
481 FILE *f = fopen("/tmp/foo.txt", "r");
482 fread(p->tail, 1, 1, f); // expected-warning {{Stream pointer might be NULL}}
483 fclose(f);
486 void gh_93408_regression_FAM0(struct FAM0 *p) {
487 FILE *f = fopen("/tmp/foo.txt", "r");
488 fread(p->tail, 1, 1, f); // expected-warning {{Stream pointer might be NULL}}
489 fclose(f);
492 struct ZeroSized {
493 int data[0];
496 void gh_93408_regression_ZeroSized(struct ZeroSized *buffer) {
497 FILE *f = fopen("/tmp/foo.txt", "r");
498 fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash
499 fclose(f);
502 extern FILE *non_standard_stream_ptr;
503 void test_fopen_does_not_alias_with_standard_streams(void) {
504 FILE *f = fopen("file", "r");
505 if (!f) return;
506 clang_analyzer_eval(f == stdin); // expected-warning {{FALSE}} no-TRUE
507 clang_analyzer_eval(f == stdout); // expected-warning {{FALSE}} no-TRUE
508 clang_analyzer_eval(f == stderr); // expected-warning {{FALSE}} no-TRUE
509 clang_analyzer_eval(f == non_standard_stream_ptr); // expected-warning {{UNKNOWN}}
510 if (f != stdout) {
511 fclose(f);
513 } // no-leak: 'fclose()' is always called because 'f' cannot be 'stdout'.
515 void reopen_std_stream(void) {
516 FILE *oldStdout = stdout;
517 fclose(stdout);
518 FILE *fp = fopen("blah", "w");
519 if (!fp) return;
521 stdout = fp; // Let's make them alias.
522 clang_analyzer_eval(fp == oldStdout); // expected-warning {{UNKNOWN}}
523 clang_analyzer_eval(fp == stdout); // expected-warning {{TRUE}} no-FALSE
524 clang_analyzer_eval(oldStdout == stdout); // expected-warning {{UNKNOWN}}
527 void only_success_path_does_not_alias_with_stdout(void) {
528 if (stdout) return;
529 FILE *f = fopen("/tmp/foof", "r"); // no-crash
530 if (!f) return;
531 fclose(f);