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