1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=unix.Stream \
4 // RUN: -analyzer-checker=debug.ExprInspection
5
6 #include "Inputs/system-header-simulator.h"
7 #include "Inputs/system-header-simulator-for-valist.h"
8
9 void clang_analyzer_eval(int);
10 void clang_analyzer_dump(int);
11
test_fread(void)12 void test_fread(void) {
13 FILE *F = fopen("file", "r+");
14 if (!F)
15 return;
16
17 char Buf[3] = {10, 10, 10};
18 fread(Buf, 1, 3, F);
19 // The check applies to success and failure.
20 clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10.
21 clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}}
22 if (feof(F)) {
23 char Buf1[3] = {10, 10, 10};
24 fread(Buf1, 1, 3, F); // expected-warning {{is in EOF state}}
25 clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}}
26 clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}}
27 }
28
29 fclose(F);
30 }
31
test_fwrite(void)32 void test_fwrite(void) {
33 FILE *F = fopen("file", "r+");
34 if (!F)
35 return;
36
37 char Buf[3] = {10, 10, 10};
38 fwrite(Buf, 1, 3, F);
39 // The check applies to success and failure.
40 clang_analyzer_dump(Buf[0]); // expected-warning {{10 S32b}}
41 clang_analyzer_dump(Buf[2]); // expected-warning {{10 S32b}}
42
43 fclose(F);
44 }
45
test_fgets()46 void test_fgets() {
47 FILE *F = tmpfile();
48 if (!F)
49 return;
50
51 char Buf[3] = {10, 10, 10};
52 fgets(Buf, 3, F);
53 // The check applies to success and failure.
54 clang_analyzer_dump(Buf[0]); // expected-warning {{conj_$}} Should not preserve the previous value, thus should not be 10.
55 clang_analyzer_dump(Buf[2]); // expected-warning {{conj_$}}
56 if (feof(F)) {
57 char Buf1[3] = {10, 10, 10};
58 fgets(Buf1, 3, F); // expected-warning {{is in EOF state}}
59 clang_analyzer_dump(Buf1[0]); // expected-warning {{10 S32b}}
60 clang_analyzer_dump(Buf1[2]); // expected-warning {{10 S32b}}
61 }
62
63 fclose(F);
64 }
65
test_fputs()66 void test_fputs() {
67 FILE *F = tmpfile();
68 if (!F)
69 return;
70
71 char *Buf = "aaa";
72 fputs(Buf, F);
73 // The check applies to success and failure.
74 clang_analyzer_dump(Buf[0]); // expected-warning {{97 S32b}}
75 clang_analyzer_dump(Buf[2]); // expected-warning {{97 S32b}}
76 clang_analyzer_dump(Buf[3]); // expected-warning {{0 S32b}}
77
78 fclose(F);
79 }
80
test_fscanf()81 void test_fscanf() {
82 FILE *F = tmpfile();
83 if (!F)
84 return;
85
86 int a = 1;
87 unsigned b;
88 int Ret = fscanf(F, "%d %u", &a, &b);
89 if (Ret == 0) {
90 clang_analyzer_dump(a); // expected-warning {{conj_$}}
91 // FIXME: should be {{1 S32b}}.
92 clang_analyzer_dump(b); // expected-warning {{conj_$}}
93 // FIXME: should be {{uninitialized value}}.
94 } else if (Ret == 1) {
95 clang_analyzer_dump(a); // expected-warning {{conj_$}}
96 clang_analyzer_dump(b); // expected-warning {{conj_$}}
97 // FIXME: should be {{uninitialized value}}.
98 } else if (Ret >= 2) {
99 clang_analyzer_dump(a); // expected-warning {{conj_$}}
100 clang_analyzer_dump(b); // expected-warning {{conj_$}}
101 clang_analyzer_eval(Ret == 2); // expected-warning {{FALSE}} expected-warning {{TRUE}}
102 // FIXME: should be only TRUE.
103 } else {
104 clang_analyzer_dump(a); // expected-warning {{1 S32b}}
105 clang_analyzer_dump(b); // expected-warning {{uninitialized value}}
106 }
107
108 fclose(F);
109 }
110
test_getdelim(char * P,size_t Sz)111 void test_getdelim(char *P, size_t Sz) {
112 FILE *F = tmpfile();
113 if (!F)
114 return;
115
116 char *P1 = P;
117 size_t Sz1 = Sz;
118 ssize_t Ret = getdelim(&P, &Sz, '\t', F);
119 if (Ret < 0) {
120 clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \
121 // expected-warning {{TRUE}}
122 clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \
123 // expected-warning {{TRUE}}
124 } else {
125 clang_analyzer_eval(P == P1); // expected-warning {{FALSE}} \
126 // expected-warning {{TRUE}}
127 clang_analyzer_eval(Sz == Sz1); // expected-warning {{FALSE}} \
128 // expected-warning {{TRUE}}
129 }
130
131 fclose(F);
132 }
133
test_fgetpos()134 void test_fgetpos() {
135 FILE *F = tmpfile();
136 if (!F)
137 return;
138
139 fpos_t Pos = 1;
140 int Ret = fgetpos(F, &Pos);
141 if (Ret == 0) {
142 clang_analyzer_dump(Pos); // expected-warning {{conj_$}}
143 } else {
144 clang_analyzer_dump(Pos); // expected-warning {{1 S32b}}
145 }
146
147 fclose(F);
148 }
149
test_fprintf()150 void test_fprintf() {
151 FILE *F1 = tmpfile();
152 if (!F1)
153 return;
154
155 unsigned a = 42;
156 char *output = "HELLO";
157 int r = fprintf(F1, "%s\t%u\n", output, a);
158 // fprintf does not invalidate any of its input
159 // 69 is ascii for 'E'
160 clang_analyzer_dump(a); // expected-warning {{42 S32b}}
161 clang_analyzer_dump(output[1]); // expected-warning {{69 S32b}}
162 fclose(F1);
163 }
164
test_vfscanf_inner(const char * fmt,...)165 int test_vfscanf_inner(const char *fmt, ...) {
166 FILE *F1 = tmpfile();
167 if (!F1)
168 return EOF;
169
170 va_list ap;
171 va_start(ap, fmt);
172
173 int r = vfscanf(F1, fmt, ap);
174
175 fclose(F1);
176 va_end(ap);
177 return r;
178 }
179
test_vfscanf()180 void test_vfscanf() {
181 int i = 42;
182 int j = 43;
183 int r = test_vfscanf_inner("%d", &i);
184 if (r != EOF) {
185 // i gets invalidated by the call to test_vfscanf_inner, not by vfscanf.
186 clang_analyzer_dump(i); // expected-warning {{conj_$}}
187 clang_analyzer_dump(j); // expected-warning {{43 S32b}}
188 }
189 }
190