1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream -verify %s
2
3 #include "Inputs/system-header-simulator.h"
4
check_fread()5 void check_fread() {
6 FILE *fp = tmpfile();
7 fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
8 fclose(fp);
9 }
10
check_fwrite()11 void check_fwrite() {
12 FILE *fp = tmpfile();
13 fwrite(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
14 fclose(fp);
15 }
16
check_fseek()17 void check_fseek() {
18 FILE *fp = tmpfile();
19 fseek(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}
20 fclose(fp);
21 }
22
check_ftell()23 void check_ftell() {
24 FILE *fp = tmpfile();
25 ftell(fp); // expected-warning {{Stream pointer might be NULL}}
26 fclose(fp);
27 }
28
check_rewind()29 void check_rewind() {
30 FILE *fp = tmpfile();
31 rewind(fp); // expected-warning {{Stream pointer might be NULL}}
32 fclose(fp);
33 }
34
check_fgetpos()35 void check_fgetpos() {
36 FILE *fp = tmpfile();
37 fpos_t pos;
38 fgetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
39 fclose(fp);
40 }
41
check_fsetpos()42 void check_fsetpos() {
43 FILE *fp = tmpfile();
44 fpos_t pos;
45 fsetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
46 fclose(fp);
47 }
48
check_clearerr()49 void check_clearerr() {
50 FILE *fp = tmpfile();
51 clearerr(fp); // expected-warning {{Stream pointer might be NULL}}
52 fclose(fp);
53 }
54
check_feof()55 void check_feof() {
56 FILE *fp = tmpfile();
57 feof(fp); // expected-warning {{Stream pointer might be NULL}}
58 fclose(fp);
59 }
60
check_ferror()61 void check_ferror() {
62 FILE *fp = tmpfile();
63 ferror(fp); // expected-warning {{Stream pointer might be NULL}}
64 fclose(fp);
65 }
66
check_fileno()67 void check_fileno() {
68 FILE *fp = tmpfile();
69 fileno(fp); // expected-warning {{Stream pointer might be NULL}}
70 fclose(fp);
71 }
72
f_open(void)73 void f_open(void) {
74 FILE *p = fopen("foo", "r");
75 char buf[1024];
76 fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL}}
77 fclose(p);
78 }
79
f_seek(void)80 void f_seek(void) {
81 FILE *p = fopen("foo", "r");
82 if (!p)
83 return;
84 fseek(p, 1, SEEK_SET); // no-warning
85 fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
86 fclose(p);
87 }
88
f_double_close(void)89 void f_double_close(void) {
90 FILE *p = fopen("foo", "r");
91 if (!p)
92 return;
93 fclose(p);
94 fclose(p); // expected-warning {{Stream might be already closed}}
95 }
96
f_double_close_alias(void)97 void f_double_close_alias(void) {
98 FILE *p1 = fopen("foo", "r");
99 if (!p1)
100 return;
101 FILE *p2 = p1;
102 fclose(p1);
103 fclose(p2); // expected-warning {{Stream might be already closed}}
104 }
105
f_use_after_close(void)106 void f_use_after_close(void) {
107 FILE *p = fopen("foo", "r");
108 if (!p)
109 return;
110 fclose(p);
111 clearerr(p); // expected-warning {{Stream might be already closed}}
112 }
113
f_open_after_close(void)114 void f_open_after_close(void) {
115 FILE *p = fopen("foo", "r");
116 if (!p)
117 return;
118 fclose(p);
119 p = fopen("foo", "r");
120 if (!p)
121 return;
122 fclose(p);
123 }
124
f_reopen_after_close(void)125 void f_reopen_after_close(void) {
126 FILE *p = fopen("foo", "r");
127 if (!p)
128 return;
129 fclose(p);
130 // Allow reopen after close.
131 p = freopen("foo", "w", p);
132 if (!p)
133 return;
134 fclose(p);
135 }
136
f_leak(int c)137 void f_leak(int c) {
138 FILE *p = fopen("foo.c", "r");
139 if (!p)
140 return;
141 if(c)
142 return; // expected-warning {{Opened stream never closed. Potential resource leak}}
143 fclose(p);
144 }
145
f_null_checked(void)146 FILE *f_null_checked(void) {
147 FILE *p = fopen("foo.c", "r");
148 if (p)
149 return p; // no-warning
150 else
151 return 0;
152 }
153
pr7831(FILE * fp)154 void pr7831(FILE *fp) {
155 fclose(fp); // no-warning
156 }
157
158 // PR 8081 - null pointer crash when 'whence' is not an integer constant
pr8081(FILE * stream,long offset,int whence)159 void pr8081(FILE *stream, long offset, int whence) {
160 fseek(stream, offset, whence);
161 }
162
check_freopen_1()163 void check_freopen_1() {
164 FILE *f1 = freopen("foo.c", "r", (FILE *)0); // expected-warning {{Stream pointer might be NULL}}
165 f1 = freopen(0, "w", (FILE *)0x123456); // Do not report this as error.
166 }
167
check_freopen_2()168 void check_freopen_2() {
169 FILE *f1 = fopen("foo.c", "r");
170 if (f1) {
171 FILE *f2 = freopen(0, "w", f1);
172 if (f2) {
173 // Check if f1 and f2 point to the same stream.
174 fclose(f1);
175 fclose(f2); // expected-warning {{Stream might be already closed.}}
176 } else {
177 // Reopen failed.
178 // f1 is non-NULL but points to a possibly invalid stream.
179 rewind(f1); // expected-warning {{Stream might be invalid}}
180 // f2 is NULL but the previous error stops the checker.
181 rewind(f2);
182 }
183 }
184 }
185
check_freopen_3()186 void check_freopen_3() {
187 FILE *f1 = fopen("foo.c", "r");
188 if (f1) {
189 // Unchecked result of freopen.
190 // The f1 may be invalid after this call.
191 freopen(0, "w", f1);
192 rewind(f1); // expected-warning {{Stream might be invalid}}
193 fclose(f1);
194 }
195 }
196
197 extern FILE *GlobalF;
198 extern void takeFile(FILE *);
199
check_escape1()200 void check_escape1() {
201 FILE *F = tmpfile();
202 if (!F)
203 return;
204 fwrite("1", 1, 1, F); // may fail
205 GlobalF = F;
206 fwrite("1", 1, 1, F); // no warning
207 }
208
check_escape2()209 void check_escape2() {
210 FILE *F = tmpfile();
211 if (!F)
212 return;
213 fwrite("1", 1, 1, F); // may fail
214 takeFile(F);
215 fwrite("1", 1, 1, F); // no warning
216 }
217
check_escape3()218 void check_escape3() {
219 FILE *F = tmpfile();
220 if (!F)
221 return;
222 takeFile(F);
223 F = freopen(0, "w", F);
224 if (!F)
225 return;
226 fwrite("1", 1, 1, F); // may fail
227 fwrite("1", 1, 1, F); // no warning
228 }
229
check_escape4()230 void check_escape4() {
231 FILE *F = tmpfile();
232 if (!F)
233 return;
234 fwrite("1", 1, 1, F); // may fail
235
236 // no escape at (non-StreamChecker-handled) system call
237 // FIXME: all such calls should be handled by the checker
238 fprintf(F, "0");
239
240 fwrite("1", 1, 1, F); // expected-warning {{might be 'indeterminate'}}
241 fclose(F);
242 }
243
244 int Test;
245 _Noreturn void handle_error();
246
check_leak_noreturn_1()247 void check_leak_noreturn_1() {
248 FILE *F1 = tmpfile();
249 if (!F1)
250 return;
251 if (Test == 1) {
252 handle_error(); // no warning
253 }
254 rewind(F1);
255 } // expected-warning {{Opened stream never closed. Potential resource leak}}
256
257 // Check that "location uniqueing" works.
258 // This results in reporting only one occurence of resource leak for a stream.
check_leak_noreturn_2()259 void check_leak_noreturn_2() {
260 FILE *F1 = tmpfile();
261 if (!F1)
262 return;
263 if (Test == 1) {
264 return; // no warning
265 }
266 rewind(F1);
267 } // expected-warning {{Opened stream never closed. Potential resource leak}}
268 // FIXME: This warning should be placed at the `return` above.
269 // See https://reviews.llvm.org/D83120 about details.
270