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