1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.Stream -analyzer-store region -verify %s
2 
3 typedef __typeof__(sizeof(int)) size_t;
4 typedef __typeof__(sizeof(int)) fpos_t;
5 typedef struct _IO_FILE FILE;
6 #define SEEK_SET	0	/* Seek from beginning of file.  */
7 #define SEEK_CUR	1	/* Seek from current position.  */
8 #define SEEK_END	2	/* Seek from end of file.  */
9 extern FILE *fopen(const char *path, const char *mode);
10 extern FILE *tmpfile(void);
11 extern int fclose(FILE *fp);
12 extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
13 extern size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
14 extern int fseek (FILE *__stream, long int __off, int __whence);
15 extern long int ftell (FILE *__stream);
16 extern void rewind (FILE *__stream);
17 extern int fgetpos(FILE *stream, fpos_t *pos);
18 extern int fsetpos(FILE *stream, const fpos_t *pos);
19 extern void clearerr(FILE *stream);
20 extern int feof(FILE *stream);
21 extern int ferror(FILE *stream);
22 extern int fileno(FILE *stream);
23 extern FILE *freopen(const char *pathname, const char *mode, FILE *stream);
24 
check_fread()25 void check_fread() {
26   FILE *fp = tmpfile();
27   fread(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
28   fclose(fp);
29 }
30 
check_fwrite()31 void check_fwrite() {
32   FILE *fp = tmpfile();
33   fwrite(0, 0, 0, fp); // expected-warning {{Stream pointer might be NULL}}
34   fclose(fp);
35 }
36 
check_fseek()37 void check_fseek() {
38   FILE *fp = tmpfile();
39   fseek(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}
40   fclose(fp);
41 }
42 
check_ftell()43 void check_ftell() {
44   FILE *fp = tmpfile();
45   ftell(fp); // expected-warning {{Stream pointer might be NULL}}
46   fclose(fp);
47 }
48 
check_rewind()49 void check_rewind() {
50   FILE *fp = tmpfile();
51   rewind(fp); // expected-warning {{Stream pointer might be NULL}}
52   fclose(fp);
53 }
54 
check_fgetpos()55 void check_fgetpos() {
56   FILE *fp = tmpfile();
57   fpos_t pos;
58   fgetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
59   fclose(fp);
60 }
61 
check_fsetpos()62 void check_fsetpos() {
63   FILE *fp = tmpfile();
64   fpos_t pos;
65   fsetpos(fp, &pos); // expected-warning {{Stream pointer might be NULL}}
66   fclose(fp);
67 }
68 
check_clearerr()69 void check_clearerr() {
70   FILE *fp = tmpfile();
71   clearerr(fp); // expected-warning {{Stream pointer might be NULL}}
72   fclose(fp);
73 }
74 
check_feof()75 void check_feof() {
76   FILE *fp = tmpfile();
77   feof(fp); // expected-warning {{Stream pointer might be NULL}}
78   fclose(fp);
79 }
80 
check_ferror()81 void check_ferror() {
82   FILE *fp = tmpfile();
83   ferror(fp); // expected-warning {{Stream pointer might be NULL}}
84   fclose(fp);
85 }
86 
check_fileno()87 void check_fileno() {
88   FILE *fp = tmpfile();
89   fileno(fp); // expected-warning {{Stream pointer might be NULL}}
90   fclose(fp);
91 }
92 
f_open(void)93 void f_open(void) {
94   FILE *p = fopen("foo", "r");
95   char buf[1024];
96   fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL}}
97   fclose(p);
98 }
99 
f_seek(void)100 void f_seek(void) {
101   FILE *p = fopen("foo", "r");
102   if (!p)
103     return;
104   fseek(p, 1, SEEK_SET); // no-warning
105   fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
106   fclose(p);
107 }
108 
f_double_close(void)109 void f_double_close(void) {
110   FILE *p = fopen("foo", "r");
111   fclose(p);
112   fclose(p); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour}}
113 }
114 
f_double_close_alias(void)115 void f_double_close_alias(void) {
116   FILE *p1 = fopen("foo", "r");
117   FILE *p2 = p1;
118   fclose(p1);
119   fclose(p2); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour}}
120 }
121 
f_leak(int c)122 void f_leak(int c) {
123   FILE *p = fopen("foo.c", "r");
124   if(c)
125     return; // expected-warning {{Opened File never closed. Potential Resource leak}}
126   fclose(p);
127 }
128 
f_null_checked(void)129 FILE *f_null_checked(void) {
130   FILE *p = fopen("foo.c", "r");
131   if (p)
132     return p; // no-warning
133   else
134     return 0;
135 }
136 
pr7831(FILE * fp)137 void pr7831(FILE *fp) {
138   fclose(fp); // no-warning
139 }
140 
141 // PR 8081 - null pointer crash when 'whence' is not an integer constant
pr8081(FILE * stream,long offset,int whence)142 void pr8081(FILE *stream, long offset, int whence) {
143   fseek(stream, offset, whence);
144 }
145 
check_freopen_1()146 void check_freopen_1() {
147   FILE *f1 = freopen("foo.c", "r", (FILE *)0); // expected-warning {{Stream pointer might be NULL}}
148   f1 = freopen(0, "w", (FILE *)0x123456);      // Do not report this as error.
149 }
150 
check_freopen_2()151 void check_freopen_2() {
152   FILE *f1 = fopen("foo.c", "r");
153   if (f1) {
154     FILE *f2 = freopen(0, "w", f1);
155     if (f2) {
156       // Check if f1 and f2 point to the same stream.
157       fclose(f1);
158       fclose(f2); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour}}
159     } else {
160       // Reopen failed.
161       // f1 points now to a possibly invalid stream but this condition is currently not checked.
162       // f2 is NULL.
163       rewind(f1);
164       rewind(f2); // expected-warning {{Stream pointer might be NULL}}
165     }
166   }
167 }
168 
check_freopen_3()169 void check_freopen_3() {
170   FILE *f1 = fopen("foo.c", "r");
171   if (f1) {
172     // Unchecked result of freopen.
173     // The f1 may be invalid after this call (not checked by the checker).
174     freopen(0, "w", f1);
175     rewind(f1);
176     fclose(f1);
177   }
178 }
179