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