1 // RUN: %clang_analyze_cc1 %s \
2 // RUN:   -analyzer-checker=core \
3 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
4 // RUN:   -analyzer-checker=debug.ExprInspection \
5 // RUN:   -analyzer-config eagerly-assume=false \
6 // RUN:   -triple i686-unknown-linux \
7 // RUN:   -verify
8 
9 // RUN: %clang_analyze_cc1 %s \
10 // RUN:   -analyzer-checker=core \
11 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
12 // RUN:   -analyzer-checker=debug.ExprInspection \
13 // RUN:   -analyzer-config eagerly-assume=false \
14 // RUN:   -triple x86_64-unknown-linux \
15 // RUN:   -verify
16 
17 // RUN: %clang_analyze_cc1 %s \
18 // RUN:   -analyzer-checker=core \
19 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
20 // RUN:   -analyzer-checker=debug.ExprInspection \
21 // RUN:   -analyzer-config eagerly-assume=false \
22 // RUN:   -triple armv7-a15-linux \
23 // RUN:   -verify
24 
25 // RUN: %clang_analyze_cc1 %s \
26 // RUN:   -analyzer-checker=core \
27 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
28 // RUN:   -analyzer-checker=debug.ExprInspection \
29 // RUN:   -analyzer-config eagerly-assume=false \
30 // RUN:   -triple thumbv7-a15-linux \
31 // RUN:   -verify
32 
33 // RUN: %clang_analyze_cc1 %s \
34 // RUN:   -analyzer-checker=core \
35 // RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
36 // RUN:   -analyzer-config apiModeling.StdCLibraryFunctions:DisplayLoadedSummaries=true \
37 // RUN:   -analyzer-checker=debug.ExprInspection \
38 // RUN:   -analyzer-config eagerly-assume=false \
39 // RUN:   -triple i686-unknown-linux 2>&1 | FileCheck %s
40 
41 //      CHECK: Loaded summary for: int isalnum(int)
42 // CHECK-NEXT: Loaded summary for: int isalpha(int)
43 // CHECK-NEXT: Loaded summary for: int isascii(int)
44 // CHECK-NEXT: Loaded summary for: int isblank(int)
45 // CHECK-NEXT: Loaded summary for: int isdigit(int)
46 // CHECK-NEXT: Loaded summary for: int isgraph(int)
47 // CHECK-NEXT: Loaded summary for: int islower(int)
48 // CHECK-NEXT: Loaded summary for: int isprint(int)
49 // CHECK-NEXT: Loaded summary for: int ispunct(int)
50 // CHECK-NEXT: Loaded summary for: int isspace(int)
51 // CHECK-NEXT: Loaded summary for: int isupper(int)
52 // CHECK-NEXT: Loaded summary for: int isxdigit(int)
53 // CHECK-NEXT: Loaded summary for: int getc(FILE *)
54 // CHECK-NEXT: Loaded summary for: int fgetc(FILE *)
55 // CHECK-NEXT: Loaded summary for: int getchar(void)
56 // CHECK-NEXT: Loaded summary for: unsigned int fread(void *restrict, size_t, size_t, FILE *restrict)
57 // CHECK-NEXT: Loaded summary for: unsigned int fwrite(const void *restrict, size_t, size_t, FILE *restrict)
58 // CHECK-NEXT: Loaded summary for: ssize_t read(int, void *, size_t)
59 // CHECK-NEXT: Loaded summary for: ssize_t write(int, const void *, size_t)
60 // CHECK-NEXT: Loaded summary for: ssize_t getline(char **restrict, size_t *restrict, FILE *restrict)
61 // CHECK-NEXT: Loaded summary for: ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict)
62 
63 
64 void clang_analyzer_eval(int);
65 
66 int glob;
67 
68 typedef struct FILE FILE;
69 #define EOF -1
70 
71 int getc(FILE *);
test_getc(FILE * fp)72 void test_getc(FILE *fp) {
73   int x;
74   while ((x = getc(fp)) != EOF) {
75     clang_analyzer_eval(x > 255); // expected-warning{{FALSE}}
76     clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}}
77   }
78 }
79 
80 int fgetc(FILE *);
test_fgets(FILE * fp)81 void test_fgets(FILE *fp) {
82   clang_analyzer_eval(fgetc(fp) < 256); // expected-warning{{TRUE}}
83   clang_analyzer_eval(fgetc(fp) >= 0); // expected-warning{{UNKNOWN}}
84 }
85 
86 
87 typedef typeof(sizeof(int)) size_t;
88 typedef signed long ssize_t;
89 ssize_t read(int, void *, size_t);
90 ssize_t write(int, const void *, size_t);
test_read_write(int fd,char * buf)91 void test_read_write(int fd, char *buf) {
92   glob = 1;
93   ssize_t x = write(fd, buf, 10);
94   clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
95   if (x >= 0) {
96     clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}}
97     ssize_t y = read(fd, &glob, sizeof(glob));
98     if (y >= 0) {
99       clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{TRUE}}
100     } else {
101       // -1 overflows on promotion!
102       clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{FALSE}}
103     }
104   } else {
105     clang_analyzer_eval(x == -1); // expected-warning{{TRUE}}
106   }
107 }
108 
109 size_t fread(void *restrict, size_t, size_t, FILE *restrict);
110 size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
test_fread_fwrite(FILE * fp,int * buf)111 void test_fread_fwrite(FILE *fp, int *buf) {
112 
113   size_t x = fwrite(buf, sizeof(int), 10, fp);
114   clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}}
115 
116   size_t y = fread(buf, sizeof(int), 10, fp);
117   clang_analyzer_eval(y <= 10); // expected-warning{{TRUE}}
118 
119   size_t z = fwrite(buf, sizeof(int), y, fp);
120   clang_analyzer_eval(z <= y); // expected-warning{{TRUE}}
121 }
122 
test_fread_uninitialized(void)123 void test_fread_uninitialized(void) {
124   void *ptr;
125   size_t sz;
126   size_t nmem;
127   FILE *fp;
128   (void)fread(ptr, sz, nmem, fp); // expected-warning {{1st function call argument is an uninitialized value}}
129 }
130 
131 ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
132 ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
test_getline(FILE * fp)133 void test_getline(FILE *fp) {
134   char *line = 0;
135   size_t n = 0;
136   ssize_t len;
137   while ((len = getline(&line, &n, fp)) != -1) {
138     clang_analyzer_eval(len == 0); // expected-warning{{FALSE}}
139   }
140 }
141 
142 int isascii(int);
test_isascii(int x)143 void test_isascii(int x) {
144   clang_analyzer_eval(isascii(123)); // expected-warning{{TRUE}}
145   clang_analyzer_eval(isascii(-1)); // expected-warning{{FALSE}}
146   if (isascii(x)) {
147     clang_analyzer_eval(x < 128); // expected-warning{{TRUE}}
148     clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}}
149   } else {
150     if (x > 42)
151       clang_analyzer_eval(x >= 128); // expected-warning{{TRUE}}
152     else
153       clang_analyzer_eval(x < 0); // expected-warning{{TRUE}}
154   }
155   glob = 1;
156   isascii('a');
157   clang_analyzer_eval(glob); // expected-warning{{TRUE}}
158 }
159 
160 int islower(int);
test_islower(int x)161 void test_islower(int x) {
162   clang_analyzer_eval(islower('x')); // expected-warning{{TRUE}}
163   clang_analyzer_eval(islower('X')); // expected-warning{{FALSE}}
164   if (islower(x))
165     clang_analyzer_eval(x < 'a'); // expected-warning{{FALSE}}
166 }
167 
168 int getchar(void);
test_getchar(void)169 void test_getchar(void) {
170   int x = getchar();
171   if (x == EOF)
172     return;
173   clang_analyzer_eval(x < 0); // expected-warning{{FALSE}}
174   clang_analyzer_eval(x < 256); // expected-warning{{TRUE}}
175 }
176 
177 int isalpha(int);
test_isalpha(void)178 void test_isalpha(void) {
179   clang_analyzer_eval(isalpha(']')); // expected-warning{{FALSE}}
180   clang_analyzer_eval(isalpha('Q')); // expected-warning{{TRUE}}
181   clang_analyzer_eval(isalpha(128)); // expected-warning{{UNKNOWN}}
182 }
183 
184 int isalnum(int);
test_alnum(void)185 void test_alnum(void) {
186   clang_analyzer_eval(isalnum('1')); // expected-warning{{TRUE}}
187   clang_analyzer_eval(isalnum(')')); // expected-warning{{FALSE}}
188 }
189 
190 int isblank(int);
test_isblank(void)191 void test_isblank(void) {
192   clang_analyzer_eval(isblank('\t')); // expected-warning{{TRUE}}
193   clang_analyzer_eval(isblank(' ')); // expected-warning{{TRUE}}
194   clang_analyzer_eval(isblank('\n')); // expected-warning{{FALSE}}
195 }
196 
197 int ispunct(int);
test_ispunct(int x)198 void test_ispunct(int x) {
199   clang_analyzer_eval(ispunct(' ')); // expected-warning{{FALSE}}
200   clang_analyzer_eval(ispunct(-1)); // expected-warning{{FALSE}}
201   clang_analyzer_eval(ispunct('#')); // expected-warning{{TRUE}}
202   clang_analyzer_eval(ispunct('_')); // expected-warning{{TRUE}}
203   if (ispunct(x))
204     clang_analyzer_eval(x < 127); // expected-warning{{TRUE}}
205 }
206 
207 int isupper(int);
test_isupper(int x)208 void test_isupper(int x) {
209   if (isupper(x))
210     clang_analyzer_eval(x < 'A'); // expected-warning{{FALSE}}
211 }
212 
213 int isgraph(int);
214 int isprint(int);
test_isgraph_isprint(int x)215 void test_isgraph_isprint(int x) {
216   char y = x;
217   if (isgraph(y))
218     clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}}
219 }
220 
221 int isdigit(int);
test_mixed_branches(int x)222 void test_mixed_branches(int x) {
223   if (isdigit(x)) {
224     clang_analyzer_eval(isgraph(x)); // expected-warning{{TRUE}}
225     clang_analyzer_eval(isblank(x)); // expected-warning{{FALSE}}
226   } else if (isascii(x)) {
227     // isalnum() bifurcates here.
228     clang_analyzer_eval(isalnum(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
229     clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
230   }
231 }
232 
233 int isspace(int);
test_isspace(int x)234 void test_isspace(int x) {
235   if (!isascii(x))
236     return;
237   char y = x;
238   if (y == ' ')
239     clang_analyzer_eval(isspace(x)); // expected-warning{{TRUE}}
240 }
241 
242 int isxdigit(int);
test_isxdigit(int x)243 void test_isxdigit(int x) {
244   if (isxdigit(x) && isupper(x)) {
245     clang_analyzer_eval(x >= 'A'); // expected-warning{{TRUE}}
246     clang_analyzer_eval(x <= 'F'); // expected-warning{{TRUE}}
247   }
248 }
249 
test_call_by_pointer(void)250 void test_call_by_pointer(void) {
251   typedef int (*func)(int);
252   func f = isascii;
253   clang_analyzer_eval(f('A')); // expected-warning{{TRUE}}
254   f = ispunct;
255   clang_analyzer_eval(f('A')); // expected-warning{{FALSE}}
256 }
257 
258 char *getenv(const char *name);
test_getenv(void)259 void test_getenv(void) {
260   // getenv() bifurcates here.
261   clang_analyzer_eval(getenv("FOO") == 0);
262   // expected-warning@-1 {{TRUE}}
263   // expected-warning@-2 {{FALSE}}
264 }
265