1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=alpha.unix.Stream \
4 // RUN: -analyzer-checker=debug.StreamTester \
5 // RUN: -analyzer-checker=debug.ExprInspection
6 
7 #include "Inputs/system-header-simulator.h"
8 
9 void clang_analyzer_eval(int);
10 void clang_analyzer_warnIfReached();
11 void StreamTesterChecker_make_feof_stream(FILE *);
12 void StreamTesterChecker_make_ferror_stream(FILE *);
13 
error_fopen()14 void error_fopen() {
15   FILE *F = fopen("file", "r");
16   if (!F)
17     return;
18   clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
19   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
20   fclose(F);
21 }
22 
error_freopen()23 void error_freopen() {
24   FILE *F = fopen("file", "r");
25   if (!F)
26     return;
27   F = freopen(0, "w", F);
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 
stream_error_feof()35 void stream_error_feof() {
36   FILE *F = fopen("file", "r");
37   if (!F)
38     return;
39   StreamTesterChecker_make_feof_stream(F);
40   clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
41   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
42   clearerr(F);
43   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
44   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
45   fclose(F);
46 }
47 
stream_error_ferror()48 void stream_error_ferror() {
49   FILE *F = fopen("file", "r");
50   if (!F)
51     return;
52   StreamTesterChecker_make_ferror_stream(F);
53   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
54   clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
55   clearerr(F);
56   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
57   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
58   fclose(F);
59 }
60 
error_fread()61 void error_fread() {
62   FILE *F = tmpfile();
63   if (!F)
64     return;
65   char Buf[10];
66   int Ret = fread(Buf, 1, 10, F);
67   if (Ret == 10) {
68     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
69   } else {
70     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{TRUE}}
71     if (feof(F)) {
72       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
73       fread(Buf, 1, 10, F);           // expected-warning {{Read function called when stream is in EOF state}}
74       clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
75       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
76     }
77     if (ferror(F)) {
78       clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
79       fread(Buf, 1, 10, F);           // expected-warning {{might be 'indeterminate'}}
80     }
81   }
82   fclose(F);
83   Ret = fread(Buf, 1, 10, F); // expected-warning {{Stream might be already closed}}
84 }
85 
error_fwrite()86 void error_fwrite() {
87   FILE *F = tmpfile();
88   if (!F)
89     return;
90   const char *Buf = "123456789";
91   int Ret = fwrite(Buf, 1, 10, F);
92   if (Ret == 10) {
93     clang_analyzer_eval(feof(F) || ferror(F)); // expected-warning {{FALSE}}
94   } else {
95     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
96     clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
97     fwrite(0, 1, 10, F);            // expected-warning {{might be 'indeterminate'}}
98   }
99   fclose(F);
100   Ret = fwrite(0, 1, 10, F); // expected-warning {{Stream might be already closed}}
101 }
102 
freadwrite_zerosize(FILE * F)103 void freadwrite_zerosize(FILE *F) {
104   fwrite(0, 1, 0, F);
105   fwrite(0, 0, 1, F);
106   fread(0, 1, 0, F);
107   fread(0, 0, 1, F);
108 }
109 
freadwrite_zerosize_eofstate(FILE * F)110 void freadwrite_zerosize_eofstate(FILE *F) {
111   fwrite(0, 1, 0, F);
112   fwrite(0, 0, 1, F);
113   fread(0, 1, 0, F); // expected-warning {{Read function called when stream is in EOF state}}
114   fread(0, 0, 1, F); // expected-warning {{Read function called when stream is in EOF state}}
115 }
116 
error_fread_fwrite_zerosize()117 void error_fread_fwrite_zerosize() {
118   FILE *F = fopen("file", "r");
119   if (!F)
120     return;
121 
122   freadwrite_zerosize(F);
123   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
124   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
125 
126   StreamTesterChecker_make_ferror_stream(F);
127   freadwrite_zerosize(F);
128   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
129   clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
130 
131   StreamTesterChecker_make_feof_stream(F);
132   freadwrite_zerosize_eofstate(F);
133   clang_analyzer_eval(feof(F));   // expected-warning {{TRUE}}
134   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
135 
136   fclose(F);
137 }
138 
error_fseek()139 void error_fseek() {
140   FILE *F = fopen("file", "r");
141   if (!F)
142     return;
143   int rc = fseek(F, 0, SEEK_SET);
144   if (rc) {
145     int IsFEof = feof(F), IsFError = ferror(F);
146     // Get feof or ferror or no error.
147     clang_analyzer_eval(IsFEof || IsFError);
148     // expected-warning@-1 {{FALSE}}
149     // expected-warning@-2 {{TRUE}}
150     clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}}
151     // Error flags should not change.
152     if (IsFEof)
153       clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}}
154     else
155       clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}}
156     if (IsFError)
157       clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
158     else
159       clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
160   } else {
161     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
162     clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
163     // Error flags should not change.
164     clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
165     clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
166   }
167   fclose(F);
168 }
169 
error_indeterminate()170 void error_indeterminate() {
171   FILE *F = fopen("file", "r+");
172   if (!F)
173     return;
174   const char *Buf = "123456789";
175   int rc = fseek(F, 0, SEEK_SET);
176   if (rc) {
177     if (feof(F)) {
178       fwrite(Buf, 1, 10, F); // no warning
179     } else if (ferror(F)) {
180       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
181     } else {
182       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
183     }
184   }
185   fclose(F);
186 }
187 
error_indeterminate_clearerr()188 void error_indeterminate_clearerr() {
189   FILE *F = fopen("file", "r+");
190   if (!F)
191     return;
192   const char *Buf = "123456789";
193   int rc = fseek(F, 0, SEEK_SET);
194   if (rc) {
195     if (feof(F)) {
196       clearerr(F);
197       fwrite(Buf, 1, 10, F); // no warning
198     } else if (ferror(F)) {
199       clearerr(F);
200       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
201     } else {
202       clearerr(F);
203       fwrite(Buf, 1, 10, F); // expected-warning {{might be 'indeterminate'}}
204     }
205   }
206   fclose(F);
207 }
208 
error_indeterminate_feof1()209 void error_indeterminate_feof1() {
210   FILE *F = fopen("file", "r+");
211   if (!F)
212     return;
213   char Buf[10];
214   if (fread(Buf, 1, 10, F) < 10) {
215     if (feof(F)) {
216       // error is feof, should be non-indeterminate
217       fwrite("1", 1, 1, F); // no warning
218     }
219   }
220   fclose(F);
221 }
222 
error_indeterminate_feof2()223 void error_indeterminate_feof2() {
224   FILE *F = fopen("file", "r+");
225   if (!F)
226     return;
227   char Buf[10];
228   if (fread(Buf, 1, 10, F) < 10) {
229     if (ferror(F) == 0) {
230       // error is feof, should be non-indeterminate
231       fwrite("1", 1, 1, F); // no warning
232     }
233   }
234   fclose(F);
235 }
236