xref: /llvm-project/clang/test/Analysis/stream-error.c (revision 2e3c7dbbcbfa37ae83251bb3da388df772680689)
1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=unix.Stream \
4 // RUN: -analyzer-config unix.Stream:Pedantic=true \
5 // RUN: -analyzer-checker=debug.StreamTester \
6 // RUN: -analyzer-checker=debug.ExprInspection
7 
8 #include "Inputs/system-header-simulator.h"
9 
10 void clang_analyzer_eval(int);
11 void clang_analyzer_dump(int);
12 void clang_analyzer_warnIfReached(void);
13 void StreamTesterChecker_make_feof_stream(FILE *);
14 void StreamTesterChecker_make_ferror_stream(FILE *);
15 void StreamTesterChecker_make_ferror_indeterminate_stream(FILE *);
16 
17 void error_fopen(void) {
18   FILE *F = fopen("file", "r");
19   if (!F)
20     return;
21   clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
22   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
23   fclose(F);
24 }
25 
26 void error_fdopen(int fd) {
27   FILE *F = fdopen(fd, "r");
28   if (!F)
29     return;
30   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
31   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
32   fclose(F);
33 }
34 
35 void error_freopen(void) {
36   FILE *F = fopen("file", "r");
37   if (!F)
38     return;
39   F = freopen(0, "w", F);
40   if (!F)
41     return;
42   clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
43   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
44   fclose(F);
45 }
46 
47 void stream_error_feof(void) {
48   FILE *F = fopen("file", "r");
49   if (!F)
50     return;
51   StreamTesterChecker_make_feof_stream(F);
52   clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
53   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
54   clearerr(F);
55   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
56   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
57   StreamTesterChecker_make_ferror_indeterminate_stream(F);
58   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
59   fclose(F);
60 }
61 
62 void stream_error_ferror(void) {
63   FILE *F = fopen("file", "r");
64   if (!F)
65     return;
66   StreamTesterChecker_make_ferror_stream(F);
67   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
68   clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
69   clearerr(F);
70   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
71   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
72   StreamTesterChecker_make_ferror_indeterminate_stream(F);
73   clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
74   fclose(F);
75 }
76 
77 void error_fread(void) {
78   FILE *F = tmpfile();
79   if (!F)
80     return;
81   char Buf[10];
82   int Ret = fread(Buf, 1, 10, F);
83   if (Ret == 10) {
84     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
85   } else {
86     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
87     if (feof(F)) {
88       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
89       fread(Buf, 1, 10, F);           // expected-warning {{Read function called when stream is in EOF state}}
90       clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
91       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
92     }
93     if (ferror(F)) {
94       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
95       fread(Buf, 1, 10, F);           // expected-warning {{might be 'indeterminate'}}
96     }
97   }
98   fclose(F);
99   Ret = fread(Buf, 1, 10, F); // expected-warning {{Use of a stream that might be already closed}}
100 }
101 
102 void error_fwrite(void) {
103   FILE *F = tmpfile();
104   if (!F)
105     return;
106   const char *Buf = "123456789";
107   int Ret = fwrite(Buf, 1, 10, F);
108   if (Ret == 10) {
109     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
110   } else {
111     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
112     clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
113     fwrite(0, 1, 10, F);            // expected-warning {{might be 'indeterminate'}}
114   }
115   fclose(F);
116   Ret = fwrite(0, 1, 10, F); // expected-warning {{Use of a stream that might be already closed}}
117 }
118 
119 void error_fgetc(void) {
120   FILE *F = tmpfile();
121   if (!F)
122     return;
123   int Ret = fgetc(F);
124   if (0 <= Ret && Ret <= 255) {
125     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
126   } else {
127     clang_analyzer_eval(Ret == EOF);           // expected-warning {{TRUE}}
128     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
129     if (feof(F)) {
130       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
131       fgetc(F);                       // expected-warning {{Read function called when stream is in EOF state}}
132     } else {
133       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
134       fgetc(F);                       // expected-warning {{might be 'indeterminate'}}
135     }
136   }
137   fclose(F);
138   fgetc(F); // expected-warning {{Use of a stream that might be already closed}}
139 }
140 
141 void error_fgets(void) {
142   FILE *F = tmpfile();
143   char Buf[256];
144   if (!F)
145     return;
146   char *Ret = fgets(Buf, sizeof(Buf), F);
147   if (Ret == Buf) {
148     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
149   } else {
150     clang_analyzer_eval(Ret == NULL);          // expected-warning {{TRUE}}
151     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
152     if (feof(F)) {
153       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
154       fgets(Buf, sizeof(Buf), F);     // expected-warning {{Read function called when stream is in EOF state}}
155     } else {
156       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
157       fgets(Buf, sizeof(Buf), F);     // expected-warning {{might be 'indeterminate'}}
158     }
159   }
160   fclose(F);
161   fgets(Buf, sizeof(Buf), F);         // expected-warning {{Use of a stream that might be already closed}}
162 }
163 
164 void error_fputc(int fd) {
165   FILE *F = fdopen(fd, "w");
166   if (!F)
167     return;
168   int Ret = fputc('X', F);
169   if (Ret == EOF) {
170     clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
171     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
172     fputc('Y', F);                  // expected-warning {{might be 'indeterminate'}}
173   } else {
174     clang_analyzer_eval(Ret == 'X');             // expected-warning {{TRUE}}
175     clang_analyzer_eval(feof(F) || ferror(F));   // expected-warning {{FALSE}}
176     fputc('Y', F);                               // no-warning
177   }
178   fclose(F);
179   fputc('A', F); // expected-warning {{Use of a stream that might be already closed}}
180 }
181 
182 void error_fputs(void) {
183   FILE *F = tmpfile();
184   if (!F)
185     return;
186   int Ret = fputs("XYZ", F);
187   if (Ret >= 0) {
188     clang_analyzer_eval(feof(F) || ferror(F));   // expected-warning {{FALSE}}
189     fputs("QWD", F);                             // no-warning
190   } else {
191     clang_analyzer_eval(Ret == EOF); // expected-warning {{TRUE}}
192     clang_analyzer_eval(ferror(F));  // expected-warning {{TRUE}}
193     clang_analyzer_eval(feof(F));    // expected-warning {{FALSE}}
194     fputs("QWD", F);                 // expected-warning {{might be 'indeterminate'}}
195   }
196   fclose(F);
197   fputs("ABC", F); // expected-warning {{Use of a stream that might be already closed}}
198 }
199 
200 void error_fprintf(void) {
201   FILE *F = tmpfile();
202   if (!F)
203     return;
204   int Ret = fprintf(F, "aaa");
205   if (Ret >= 0) {
206     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
207     fprintf(F, "bbb");                         // no-warning
208   } else {
209     clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
210     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
211     fprintf(F, "bbb");              // expected-warning {{might be 'indeterminate'}}
212   }
213   fclose(F);
214   fprintf(F, "ccc"); // expected-warning {{Use of a stream that might be already closed}}
215 }
216 
217 void error_fscanf(int *A) {
218   FILE *F = tmpfile();
219   if (!F)
220     return;
221   int Ret = fscanf(F, "a%ib", A);
222   if (Ret >= 0) {
223     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
224     fscanf(F, "bbb");                          // no-warning
225   } else {
226     if (ferror(F)) {
227       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
228       fscanf(F, "bbb");               // expected-warning {{might be 'indeterminate'}}
229     } else if (feof(F)) {
230       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
231       fscanf(F, "bbb");               // expected-warning {{is in EOF state}}
232       clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
233     } else {
234       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
235       fscanf(F, "bbb");               // expected-warning {{might be 'indeterminate'}}
236     }
237   }
238   fclose(F);
239   fscanf(F, "ccc"); // expected-warning {{Use of a stream that might be already closed}}
240 }
241 
242 void error_ungetc(int TestIndeterminate) {
243   FILE *F = tmpfile();
244   if (!F)
245     return;
246   int Ret = ungetc('X', F);
247   clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
248   if (Ret == EOF) {
249     clang_analyzer_warnIfReached();          // expected-warning {{REACHABLE}}
250   } else {
251     clang_analyzer_eval(Ret == 'X');         // expected-warning {{TRUE}}
252   }
253   fputc('Y', F);                             // no-warning
254   if (TestIndeterminate) {
255     StreamTesterChecker_make_ferror_indeterminate_stream(F);
256     ungetc('X', F);                          // expected-warning {{might be 'indeterminate'}}
257   }
258   fclose(F);
259   ungetc('A', F);                            // expected-warning {{Use of a stream that might be already closed}}
260 }
261 
262 void error_getdelim(char *P, size_t Sz) {
263   FILE *F = tmpfile();
264   if (!F)
265     return;
266   ssize_t Ret = getdelim(&P, &Sz, '\t', F);
267   if (Ret >= 0) {
268     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
269   } else {
270     clang_analyzer_eval(Ret == -1);            // expected-warning {{TRUE}}
271     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
272     if (feof(F)) {
273       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
274       getdelim(&P, &Sz, '\n', F);     // expected-warning {{Read function called when stream is in EOF state}}
275     } else {
276       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
277       getdelim(&P, &Sz, '\n', F);     // expected-warning {{might be 'indeterminate'}}
278     }
279   }
280   fclose(F);
281   getdelim(&P, &Sz, '\n', F);         // expected-warning {{Use of a stream that might be already closed}}
282 }
283 
284 void error_getline(char *P, size_t Sz) {
285   FILE *F = tmpfile();
286   if (!F)
287     return;
288   ssize_t Ret = getline(&P, &Sz, F);
289   if (Ret >= 0) {
290     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
291   } else {
292     clang_analyzer_eval(Ret == -1);            // expected-warning {{TRUE}}
293     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
294     if (feof(F)) {
295       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
296       getline(&P, &Sz, F);            // expected-warning {{Read function called when stream is in EOF state}}
297     } else {
298       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
299       getline(&P, &Sz, F);            // expected-warning {{might be 'indeterminate'}}
300     }
301   }
302   fclose(F);
303   getline(&P, &Sz, F);                // expected-warning {{Use of a stream that might be already closed}}
304 }
305 
306 void write_after_eof_is_allowed(void) {
307   FILE *F = tmpfile();
308   if (!F)
309     return;
310   StreamTesterChecker_make_feof_stream(F);
311   if (fputs("QWD", F) >= 0)                    // no-warning
312     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
313   StreamTesterChecker_make_feof_stream(F);
314   if (fputc('Q', F) == 'Q')                    // no-warning
315     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
316   StreamTesterChecker_make_feof_stream(F);
317   if (fwrite("012345678", 1, 10, F) == 10)     // no-warning
318     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
319   fclose(F);
320 }
321 
322 void freadwrite_zerosize(FILE *F) {
323   size_t Ret;
324   Ret = fwrite(0, 1, 0, F);
325   clang_analyzer_dump(Ret); // expected-warning {{0 }}
326   Ret = fwrite(0, 0, 1, F);
327   clang_analyzer_dump(Ret); // expected-warning {{0 }}
328   Ret = fread(0, 1, 0, F);
329   clang_analyzer_dump(Ret); // expected-warning {{0 }}
330   Ret = fread(0, 0, 1, F);
331   clang_analyzer_dump(Ret); // expected-warning {{0 }}
332 }
333 
334 void freadwrite_zerosize_eofstate(FILE *F) {
335   fwrite(0, 1, 0, F);
336   fwrite(0, 0, 1, F);
337   fread(0, 1, 0, F); // expected-warning {{Read function called when stream is in EOF state}}
338   fread(0, 0, 1, F); // expected-warning {{Read function called when stream is in EOF state}}
339 }
340 
341 void error_fread_fwrite_zerosize(void) {
342   FILE *F = fopen("file", "r");
343   if (!F)
344     return;
345 
346   freadwrite_zerosize(F);
347   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
348   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
349 
350   StreamTesterChecker_make_ferror_stream(F);
351   freadwrite_zerosize(F);
352   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
353   clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
354 
355   StreamTesterChecker_make_feof_stream(F);
356   freadwrite_zerosize_eofstate(F);
357   clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
358   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
359 
360   fclose(F);
361 }
362 
363 void error_fseek(void) {
364   FILE *F = fopen("file", "r");
365   if (!F)
366     return;
367   int rc = fseek(F, 1, SEEK_SET);
368   if (rc) {
369     clang_analyzer_eval(rc == -1);     // expected-warning {{TRUE}}
370     int IsFEof = feof(F), IsFError = ferror(F);
371     // Get ferror or no error.
372     clang_analyzer_eval(IsFError);     // expected-warning {{FALSE}} \
373                                        // expected-warning {{TRUE}}
374     clang_analyzer_eval(IsFEof);       // expected-warning {{FALSE}}
375     // Error flags should not change.
376     clang_analyzer_eval(feof(F));      // expected-warning {{FALSE}}
377     if (IsFError)
378       clang_analyzer_eval(ferror(F));  // expected-warning {{TRUE}}
379   } else {
380     clang_analyzer_eval(feof(F));      // expected-warning {{FALSE}}
381     clang_analyzer_eval(ferror(F));    // expected-warning {{FALSE}}
382     // Error flags should not change.
383     clang_analyzer_eval(feof(F));      // expected-warning {{FALSE}}
384     clang_analyzer_eval(ferror(F));    // expected-warning {{FALSE}}
385   }
386   fclose(F);
387 }
388 
389 void error_fseeko(void) {
390   FILE *F = fopen("file", "r");
391   if (!F)
392     return;
393   int rc = fseeko(F, 1, SEEK_SET);
394   if (rc) {
395     // Get ferror or no error.
396     clang_analyzer_eval(ferror(F));  // expected-warning {{FALSE}} \
397                                      // expected-warning {{TRUE}}
398     clang_analyzer_eval(feof(F));    // expected-warning {{FALSE}}
399   } else {
400     clang_analyzer_eval(feof(F));    // expected-warning {{FALSE}}
401     clang_analyzer_eval(ferror(F));  // expected-warning {{FALSE}}
402   }
403   fclose(F);
404 }
405 
406 void error_fseek_0(void) {
407   FILE *F = fopen("file", "r");
408   if (!F)
409     return;
410   int rc = fseek(F, 0, SEEK_SET);
411   if (rc == -1) {
412     int IsFEof = feof(F), IsFError = ferror(F);
413     // Get ferror or no error, but not feof.
414     clang_analyzer_eval(IsFError);
415     // expected-warning@-1 {{FALSE}}
416     // expected-warning@-2 {{TRUE}}
417     clang_analyzer_eval(IsFEof);
418     // expected-warning@-1 {{FALSE}}
419     // Error flags should not change.
420     clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
421     if (IsFError)
422       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
423     else
424       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
425   } else {
426     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
427     clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
428     // Error flags should not change.
429     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
430     clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
431   }
432   fclose(F);
433 }
434 
435 void error_fseeko_0(void) {
436   FILE *F = fopen("file", "r");
437   if (!F)
438     return;
439   int rc = fseeko(F, 0, SEEK_SET);
440   if (rc) {
441     int IsFEof = feof(F), IsFError = ferror(F);
442     // Get ferror or no error, but not feof.
443     clang_analyzer_eval(IsFError);
444     // expected-warning@-1 {{FALSE}}
445     // expected-warning@-2 {{TRUE}}
446     clang_analyzer_eval(IsFEof);
447     // expected-warning@-1 {{FALSE}}
448   } else {
449     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
450     clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
451   }
452   fclose(F);
453 }
454 
455 void error_ftell(int TestIndeterminate) {
456   FILE *F = fopen("file", "r");
457   if (!F)
458     return;
459   long rc = ftell(F);
460   if (rc >= 0)
461     clang_analyzer_warnIfReached();          // expected-warning {{REACHABLE}}
462   else
463     clang_analyzer_eval(rc == -1);           // expected-warning {{TRUE}}
464   clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
465   StreamTesterChecker_make_feof_stream(F);
466   rc = ftell(F);
467   clang_analyzer_eval(feof(F));              // expected-warning {{TRUE}}
468   clang_analyzer_eval(ferror(F));            // expected-warning {{FALSE}}
469   StreamTesterChecker_make_ferror_stream(F);
470   rc = ftell(F);
471   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
472   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
473   if (TestIndeterminate) {
474     StreamTesterChecker_make_ferror_indeterminate_stream(F);
475     ftell(F);                                // expected-warning {{might be 'indeterminate'}}
476   }
477   fclose(F);
478 }
479 
480 void error_ftello(int TestIndeterminate) {
481   FILE *F = fopen("file", "r");
482   if (!F)
483     return;
484   off_t rc = ftello(F);
485   if (rc >= 0)
486     clang_analyzer_warnIfReached();          // expected-warning {{REACHABLE}}
487   else
488     clang_analyzer_eval(rc == -1);           // expected-warning {{TRUE}}
489   clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
490   StreamTesterChecker_make_feof_stream(F);
491   rc = ftello(F);
492   clang_analyzer_eval(feof(F));              // expected-warning {{TRUE}}
493   clang_analyzer_eval(ferror(F));            // expected-warning {{FALSE}}
494   StreamTesterChecker_make_ferror_stream(F);
495   rc = ftello(F);
496   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
497   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
498   if (TestIndeterminate) {
499     StreamTesterChecker_make_ferror_indeterminate_stream(F);
500     ftell(F);                                // expected-warning {{might be 'indeterminate'}}
501   }
502   fclose(F);
503 }
504 
505 void error_fileno(void) {
506   FILE *F = fopen("file", "r");
507   if (!F)
508     return;
509   int N = fileno(F);
510   clang_analyzer_eval(N >= 0); // expected-warning {{TRUE}}
511   clang_analyzer_eval(feof(F) && ferror(F)); // expected-warning {{FALSE}}
512   StreamTesterChecker_make_feof_stream(F);
513   N = fileno(F);
514   clang_analyzer_eval(feof(F));              // expected-warning {{TRUE}}
515   clang_analyzer_eval(ferror(F));            // expected-warning {{FALSE}}
516   StreamTesterChecker_make_ferror_stream(F);
517   N = fileno(F);
518   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
519   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
520   StreamTesterChecker_make_ferror_indeterminate_stream(F);
521   fileno(F);                                 // no warning
522   fclose(F);
523 }
524 
525 void error_fflush_on_non_null_stream_clear_error_states(void) {
526   FILE *F0 = tmpfile(), *F1 = tmpfile();
527   // `fflush` clears a non-EOF stream's error state.
528   if (F0) {
529     StreamTesterChecker_make_ferror_stream(F0);
530     if (fflush(F0) == 0) {             // no-warning
531       clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}}
532       clang_analyzer_eval(feof(F0));   // expected-warning {{FALSE}}
533     }
534     fclose(F0);
535   }
536   // `fflush` clears an EOF stream's error state.
537   if (F1) {
538     StreamTesterChecker_make_feof_stream(F1);
539     if (fflush(F1) == 0) {             // no-warning
540       clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}}
541       clang_analyzer_eval(feof(F1));   // expected-warning {{TRUE}}
542     }
543     fclose(F1);
544   }
545 }
546 
547 void error_fflush_on_null_stream_clear_error_states(void) {
548   FILE *F0 = tmpfile(), *F1 = tmpfile();
549   // `fflush` clears all stream's error states, while retains their EOF states.
550   if (F0 && F1) {
551     StreamTesterChecker_make_ferror_stream(F0);
552     StreamTesterChecker_make_feof_stream(F1);
553     if (fflush(NULL) == 0) {           // no-warning
554       clang_analyzer_eval(ferror(F0)); // expected-warning {{FALSE}}
555       clang_analyzer_eval(feof(F0));   // expected-warning {{FALSE}}
556       clang_analyzer_eval(ferror(F1)); // expected-warning {{FALSE}}
557       clang_analyzer_eval(feof(F1));   // expected-warning {{TRUE}}
558     }
559   }
560   if (F0)
561     fclose(F0);
562   if (F1)
563     fclose(F1);
564 }
565 
566 void error_indeterminate(void) {
567   FILE *F = fopen("file", "r+");
568   if (!F)
569     return;
570   const char *Buf = "123456789";
571   int rc = fseek(F, 0, SEEK_SET);
572   if (rc) {
573     if (feof(F)) {
574       fwrite(Buf, 1, 10, F); // no warning
575     } else if (ferror(F)) {
576       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
577     } else {
578       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
579     }
580   }
581   fclose(F);
582 }
583 
584 void error_indeterminate_clearerr(void) {
585   FILE *F = fopen("file", "r+");
586   if (!F)
587     return;
588   const char *Buf = "123456789";
589   int rc = fseek(F, 0, SEEK_SET);
590   if (rc) {
591     if (feof(F)) {
592       clearerr(F);
593       fwrite(Buf, 1, 10, F); // no warning
594     } else if (ferror(F)) {
595       clearerr(F);
596       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
597     } else {
598       clearerr(F);
599       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
600     }
601   }
602   fclose(F);
603 }
604 
605 void error_indeterminate_feof1(void) {
606   FILE *F = fopen("file", "r+");
607   if (!F)
608     return;
609   char Buf[10];
610   if (fread(Buf, 1, 10, F) < 10) {
611     if (feof(F)) {
612       // error is feof, should be non-indeterminate
613       fwrite("1", 1, 1, F); // no warning
614     }
615   }
616   fclose(F);
617 }
618 
619 void error_indeterminate_feof2(void) {
620   FILE *F = fopen("file", "r+");
621   if (!F)
622     return;
623   char Buf[10];
624   if (fread(Buf, 1, 10, F) < 10) {
625     if (ferror(F) == 0) {
626       // error is feof, should be non-indeterminate
627       fwrite("1", 1, 1, F); // no warning
628     }
629   }
630   fclose(F);
631 }
632