1 // Check the basic reporting/warning and the application of constraints. 2 // RUN: %clang_analyze_cc1 %s \ 3 // RUN: -analyzer-checker=core \ 4 // RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \ 5 // RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \ 6 // RUN: -analyzer-checker=debug.StdCLibraryFunctionsTester \ 7 // RUN: -analyzer-checker=debug.ExprInspection \ 8 // RUN: -triple x86_64-unknown-linux-gnu \ 9 // RUN: -verify=report 10 11 // Check the bugpath related to the reports. 12 // RUN: %clang_analyze_cc1 %s \ 13 // RUN: -analyzer-checker=core \ 14 // RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \ 15 // RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \ 16 // RUN: -analyzer-checker=debug.StdCLibraryFunctionsTester \ 17 // RUN: -analyzer-checker=debug.ExprInspection \ 18 // RUN: -triple x86_64-unknown-linux-gnu \ 19 // RUN: -analyzer-output=text \ 20 // RUN: -verify=bugpath 21 22 void clang_analyzer_eval(int); 23 void clang_analyzer_warnIfReached(); 24 25 int glob; 26 27 #define EOF -1 28 29 int isalnum(int); 30 31 void test_alnum_concrete(int v) { 32 int ret = isalnum(256); // \ 33 // report-warning{{Function argument constraint is not satisfied}} \ 34 // report-note{{}} \ 35 // bugpath-warning{{Function argument constraint is not satisfied}} \ 36 // bugpath-note{{}} \ 37 // bugpath-note{{Function argument constraint is not satisfied}} 38 (void)ret; 39 } 40 41 void test_alnum_symbolic(int x) { 42 int ret = isalnum(x); // \ 43 // bugpath-note{{Assuming the character is non-alphanumeric}} 44 (void)ret; 45 46 clang_analyzer_eval(EOF <= x && x <= 255); // \ 47 // report-warning{{TRUE}} \ 48 // bugpath-warning{{TRUE}} \ 49 // bugpath-note{{TRUE}} \ 50 // bugpath-note{{Left side of '&&' is true}} \ 51 // bugpath-note{{'x' is <= 255}} 52 } 53 54 void test_alnum_symbolic2(int x) { 55 if (x > 255) { // \ 56 // bugpath-note{{Assuming 'x' is > 255}} \ 57 // bugpath-note{{Taking true branch}} 58 59 int ret = isalnum(x); // \ 60 // report-warning{{Function argument constraint is not satisfied}} \ 61 // report-note{{}} \ 62 // bugpath-warning{{Function argument constraint is not satisfied}} \ 63 // bugpath-note{{}} \ 64 // bugpath-note{{Function argument constraint is not satisfied}} 65 66 (void)ret; 67 } 68 } 69 70 int toupper(int); 71 72 void test_toupper_concrete(int v) { 73 int ret = toupper(256); // \ 74 // report-warning{{Function argument constraint is not satisfied}} \ 75 // report-note{{}} \ 76 // bugpath-warning{{Function argument constraint is not satisfied}} \ 77 // bugpath-note{{}} \ 78 // bugpath-note{{Function argument constraint is not satisfied}} 79 (void)ret; 80 } 81 82 void test_toupper_symbolic(int x) { 83 int ret = toupper(x); 84 (void)ret; 85 86 clang_analyzer_eval(EOF <= x && x <= 255); // \ 87 // report-warning{{TRUE}} \ 88 // bugpath-warning{{TRUE}} \ 89 // bugpath-note{{TRUE}} \ 90 // bugpath-note{{Left side of '&&' is true}} \ 91 // bugpath-note{{'x' is <= 255}} 92 } 93 94 void test_toupper_symbolic2(int x) { 95 if (x > 255) { // \ 96 // bugpath-note{{Assuming 'x' is > 255}} \ 97 // bugpath-note{{Taking true branch}} 98 99 int ret = toupper(x); // \ 100 // report-warning{{Function argument constraint is not satisfied}} \ 101 // report-note{{}} \ 102 // bugpath-warning{{Function argument constraint is not satisfied}} \ 103 // bugpath-note{{}} \ 104 // bugpath-note{{Function argument constraint is not satisfied}} 105 106 (void)ret; 107 } 108 } 109 110 int tolower(int); 111 112 void test_tolower_concrete(int v) { 113 int ret = tolower(256); // \ 114 // report-warning{{Function argument constraint is not satisfied}} \ 115 // report-note{{}} \ 116 // bugpath-warning{{Function argument constraint is not satisfied}} \ 117 // bugpath-note{{}} \ 118 // bugpath-note{{Function argument constraint is not satisfied}} 119 (void)ret; 120 } 121 122 void test_tolower_symbolic(int x) { 123 int ret = tolower(x); 124 (void)ret; 125 126 clang_analyzer_eval(EOF <= x && x <= 255); // \ 127 // report-warning{{TRUE}} \ 128 // bugpath-warning{{TRUE}} \ 129 // bugpath-note{{TRUE}} \ 130 // bugpath-note{{Left side of '&&' is true}} \ 131 // bugpath-note{{'x' is <= 255}} 132 } 133 134 void test_tolower_symbolic2(int x) { 135 if (x > 255) { // \ 136 // bugpath-note{{Assuming 'x' is > 255}} \ 137 // bugpath-note{{Taking true branch}} 138 139 int ret = tolower(x); // \ 140 // report-warning{{Function argument constraint is not satisfied}} \ 141 // report-note{{}} \ 142 // bugpath-warning{{Function argument constraint is not satisfied}} \ 143 // bugpath-note{{}} \ 144 // bugpath-note{{Function argument constraint is not satisfied}} 145 146 (void)ret; 147 } 148 } 149 150 int toascii(int); 151 152 void test_toascii_concrete(int v) { 153 int ret = toascii(256); // \ 154 // report-warning{{Function argument constraint is not satisfied}} \ 155 // report-note{{}} \ 156 // bugpath-warning{{Function argument constraint is not satisfied}} \ 157 // bugpath-note{{}} \ 158 // bugpath-note{{Function argument constraint is not satisfied}} 159 (void)ret; 160 } 161 162 void test_toascii_symbolic(int x) { 163 int ret = toascii(x); 164 (void)ret; 165 166 clang_analyzer_eval(EOF <= x && x <= 255); // \ 167 // report-warning{{TRUE}} \ 168 // bugpath-warning{{TRUE}} \ 169 // bugpath-note{{TRUE}} \ 170 // bugpath-note{{Left side of '&&' is true}} \ 171 // bugpath-note{{'x' is <= 255}} 172 } 173 174 void test_toascii_symbolic2(int x) { 175 if (x > 255) { // \ 176 // bugpath-note{{Assuming 'x' is > 255}} \ 177 // bugpath-note{{Taking true branch}} 178 179 int ret = toascii(x); // \ 180 // report-warning{{Function argument constraint is not satisfied}} \ 181 // report-note{{}} \ 182 // bugpath-warning{{Function argument constraint is not satisfied}} \ 183 // bugpath-note{{}} \ 184 // bugpath-note{{Function argument constraint is not satisfied}} 185 186 (void)ret; 187 } 188 } 189 190 typedef struct FILE FILE; 191 typedef typeof(sizeof(int)) size_t; 192 size_t fread(void *restrict, size_t, size_t, FILE *restrict); 193 void test_notnull_concrete(FILE *fp) { 194 fread(0, sizeof(int), 10, fp); // \ 195 // report-warning{{Function argument constraint is not satisfied}} \ 196 // report-note{{}} \ 197 // bugpath-warning{{Function argument constraint is not satisfied}} \ 198 // bugpath-note{{}} \ 199 // bugpath-note{{Function argument constraint is not satisfied}} 200 } 201 void test_notnull_symbolic(FILE *fp, int *buf) { 202 fread(buf, sizeof(int), 10, fp); 203 clang_analyzer_eval(buf != 0); // \ 204 // report-warning{{TRUE}} \ 205 // bugpath-warning{{TRUE}} \ 206 // bugpath-note{{TRUE}} \ 207 // bugpath-note{{'buf' is not equal to null}} 208 } 209 void test_notnull_symbolic2(FILE *fp, int *buf) { 210 if (!buf) // bugpath-note{{Assuming 'buf' is null}} \ 211 // bugpath-note{{Taking true branch}} 212 fread(buf, sizeof(int), 10, fp); // \ 213 // report-warning{{Function argument constraint is not satisfied}} \ 214 // report-note{{}} \ 215 // bugpath-warning{{Function argument constraint is not satisfied}} \ 216 // bugpath-note{{}} \ 217 // bugpath-note{{Function argument constraint is not satisfied}} 218 } 219 void test_no_node_after_bug(FILE *fp, size_t size, size_t n, void *buf) { 220 if (fp) // \ 221 // bugpath-note{{Assuming 'fp' is null}} \ 222 // bugpath-note{{Taking false branch}} 223 return; 224 size_t ret = fread(buf, size, n, fp); // \ 225 // report-warning{{Function argument constraint is not satisfied}} \ 226 // report-note{{}} \ 227 // bugpath-warning{{Function argument constraint is not satisfied}} \ 228 // bugpath-note{{}} \ 229 // bugpath-note{{Function argument constraint is not satisfied}} 230 clang_analyzer_warnIfReached(); // not reachable 231 } 232 233 typedef __WCHAR_TYPE__ wchar_t; 234 // This is one test case for the ARR38-C SEI-CERT rule. 235 void ARR38_C_F(FILE *file) { 236 enum { BUFFER_SIZE = 1024 }; 237 wchar_t wbuf[BUFFER_SIZE]; // bugpath-note{{'wbuf' initialized here}} 238 239 const size_t size = sizeof(*wbuf); // bugpath-note{{'size' initialized to}} 240 const size_t nitems = sizeof(wbuf); // bugpath-note{{'nitems' initialized to}} 241 242 // The 3rd parameter should be the number of elements to read, not 243 // the size in bytes. 244 fread(wbuf, size, nitems, file); // \ 245 // report-warning{{Function argument constraint is not satisfied}} \ 246 // report-note{{}} \ 247 // bugpath-warning{{Function argument constraint is not satisfied}} \ 248 // bugpath-note{{}} \ 249 // bugpath-note{{Function argument constraint is not satisfied}} 250 } 251 252 int __two_constrained_args(int, int); 253 void test_constraints_on_multiple_args(int x, int y) { 254 // State split should not happen here. I.e. x == 1 should not be evaluated 255 // FALSE. 256 __two_constrained_args(x, y); 257 //NOTE! Because of the second `clang_analyzer_eval` call we have two bug 258 clang_analyzer_eval(x == 1); // \ 259 // report-warning{{TRUE}} \ 260 // bugpath-warning{{TRUE}} \ 261 // bugpath-note{{TRUE}} 262 clang_analyzer_eval(y == 1); // \ 263 // report-warning{{TRUE}} \ 264 // bugpath-warning{{TRUE}} \ 265 // bugpath-note{{TRUE}} 266 } 267 268 int __arg_constrained_twice(int); 269 void test_multiple_constraints_on_same_arg(int x) { 270 __arg_constrained_twice(x); 271 clang_analyzer_eval(x < 1 || x > 2); // \ 272 // report-warning{{TRUE}} \ 273 // bugpath-warning{{TRUE}} \ 274 // bugpath-note{{TRUE}} \ 275 // bugpath-note{{Assuming 'x' is < 1}} \ 276 // bugpath-note{{Left side of '||' is true}} 277 } 278 279 int __variadic(void *stream, const char *format, ...); 280 void test_arg_constraint_on_variadic_fun(void) { 281 __variadic(0, "%d%d", 1, 2); // \ 282 // report-warning{{Function argument constraint is not satisfied}} \ 283 // report-note{{}} \ 284 // bugpath-warning{{Function argument constraint is not satisfied}} \ 285 // bugpath-note{{}} \ 286 // bugpath-note{{Function argument constraint is not satisfied}} 287 } 288 289 int __buf_size_arg_constraint(const void *, size_t); 290 void test_buf_size_concrete(void) { 291 char buf[3]; // bugpath-note{{'buf' initialized here}} 292 __buf_size_arg_constraint(buf, 4); // \ 293 // report-warning{{Function argument constraint is not satisfied}} \ 294 // report-note{{}} \ 295 // bugpath-warning{{Function argument constraint is not satisfied}} \ 296 // bugpath-note{{}} \ 297 // bugpath-note{{Function argument constraint is not satisfied}} 298 } 299 void test_buf_size_symbolic(int s) { 300 char buf[3]; 301 __buf_size_arg_constraint(buf, s); 302 clang_analyzer_eval(s <= 3); // \ 303 // report-warning{{TRUE}} \ 304 // bugpath-warning{{TRUE}} \ 305 // bugpath-note{{TRUE}} \ 306 // bugpath-note{{'s' is <= 3}} 307 } 308 void test_buf_size_symbolic_and_offset(int s) { 309 char buf[3]; 310 __buf_size_arg_constraint(buf + 1, s); 311 clang_analyzer_eval(s <= 2); // \ 312 // report-warning{{TRUE}} \ 313 // bugpath-warning{{TRUE}} \ 314 // bugpath-note{{TRUE}} \ 315 // bugpath-note{{'s' is <= 2}} 316 } 317 318 int __buf_size_arg_constraint_mul(const void *, size_t, size_t); 319 void test_buf_size_concrete_with_multiplication(void) { 320 short buf[3]; // bugpath-note{{'buf' initialized here}} 321 __buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \ 322 // report-warning{{Function argument constraint is not satisfied}} \ 323 // report-note{{}} \ 324 // bugpath-warning{{Function argument constraint is not satisfied}} \ 325 // bugpath-note{{}} \ 326 // bugpath-note{{Function argument constraint is not satisfied}} 327 } 328 void test_buf_size_symbolic_with_multiplication(size_t s) { 329 short buf[3]; 330 __buf_size_arg_constraint_mul(buf, s, sizeof(short)); 331 clang_analyzer_eval(s * sizeof(short) <= 6); // \ 332 // report-warning{{TRUE}} \ 333 // bugpath-warning{{TRUE}} \ 334 // bugpath-note{{TRUE}} 335 } 336 void test_buf_size_symbolic_and_offset_with_multiplication(size_t s) { 337 short buf[3]; 338 __buf_size_arg_constraint_mul(buf + 1, s, sizeof(short)); 339 clang_analyzer_eval(s * sizeof(short) <= 4); // \ 340 // report-warning{{TRUE}} \ 341 // bugpath-warning{{TRUE}} \ 342 // bugpath-note{{TRUE}} 343 } 344 345 // The minimum buffer size for this function is set to 10. 346 int __buf_size_arg_constraint_concrete(const void *); 347 void test_min_buf_size(void) { 348 char buf[9];// bugpath-note{{'buf' initialized here}} 349 __buf_size_arg_constraint_concrete(buf); // \ 350 // report-warning{{Function argument constraint is not satisfied}} \ 351 // report-note{{}} \ 352 // bugpath-warning{{Function argument constraint is not satisfied}} \ 353 // bugpath-note{{}} \ 354 // bugpath-note{{Function argument constraint is not satisfied}} 355 } 356