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