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