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