921 lines · c
1// Given code 'struct aa { char s1[4]; char * s2;} a; memcpy(a.s1, ...);',2// this test checks that the CStringChecker only invalidates the destination buffer array a.s1 (instead of a.s1 and a.s2).3// At the moment the whole of the destination array content is invalidated.4// If a.s1 region has a symbolic offset, the whole region of 'a' is invalidated.5// Specific triple set to test structures of size 0.6// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-disable-checker=core.FixedAddressDereference -Wno-error=int-conversion -verify -analyzer-config eagerly-assume=false %s7 8typedef __typeof(sizeof(int)) size_t;9 10char *strdup(const char *s);11void free(void *);12void *memcpy(void *dst, const void *src, size_t n); // expected-note{{passing argument to parameter 'dst' here}}13void *malloc(size_t n);14 15void clang_analyzer_eval(int);16 17struct aa {18 char s1[4];19 char *s2;20};21 22// Test different types of structure initialisation.23int f0(void) {24 struct aa a0 = {{1, 2, 3, 4}, 0};25 a0.s2 = strdup("hello");26 char input[] = {'a', 'b', 'c', 'd'};27 memcpy(a0.s1, input, 4);28 clang_analyzer_eval(a0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}29 clang_analyzer_eval(a0.s1[1] == 'b'); // expected-warning{{UNKNOWN}}30 clang_analyzer_eval(a0.s1[2] == 'c'); // expected-warning{{UNKNOWN}}31 clang_analyzer_eval(a0.s1[3] == 'd'); // expected-warning{{UNKNOWN}}32 clang_analyzer_eval(a0.s2 == 0); // expected-warning{{UNKNOWN}}33 free(a0.s2); // no warning34 return 0;35}36 37int f1(void) {38 struct aa a1;39 a1.s2 = strdup("hello");40 char input[] = {'a', 'b', 'c', 'd'};41 memcpy(a1.s1, input, 4);42 clang_analyzer_eval(a1.s1[0] == 'a'); // expected-warning{{UNKNOWN}}43 clang_analyzer_eval(a1.s1[1] == 'b'); // expected-warning{{UNKNOWN}}44 clang_analyzer_eval(a1.s1[2] == 'c'); // expected-warning{{UNKNOWN}}45 clang_analyzer_eval(a1.s1[3] == 'd'); // expected-warning{{UNKNOWN}}46 clang_analyzer_eval(a1.s2 == 0); // expected-warning{{UNKNOWN}}47 free(a1.s2); // no warning48 return 0;49}50 51int f2(void) {52 struct aa a2 = {{1, 2}};53 a2.s2 = strdup("hello");54 char input[] = {'a', 'b', 'c', 'd'};55 memcpy(a2.s1, input, 4);56 clang_analyzer_eval(a2.s1[0] == 'a'); // expected-warning{{UNKNOWN}}57 clang_analyzer_eval(a2.s1[1] == 'b'); // expected-warning{{UNKNOWN}}58 clang_analyzer_eval(a2.s1[2] == 'c'); // expected-warning{{UNKNOWN}}59 clang_analyzer_eval(a2.s1[3] == 'd'); // expected-warning{{UNKNOWN}}60 clang_analyzer_eval(a2.s2 == 0); // expected-warning{{UNKNOWN}}61 free(a2.s2); // no warning62 return 0;63}64 65int f3(void) {66 struct aa a3 = {{1, 2, 3, 4}, 0};67 a3.s2 = strdup("hello");68 char input[] = {'a', 'b', 'c', 'd'};69 int * dest = (int*)a3.s1;70 memcpy(dest, input, 4);71 clang_analyzer_eval(a3.s1[0] == 'a'); // expected-warning{{UNKNOWN}}72 clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}}73 clang_analyzer_eval(a3.s1[1] == 'b'); // expected-warning{{UNKNOWN}}74 clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}}75 clang_analyzer_eval(a3.s1[2] == 'c'); // expected-warning{{UNKNOWN}}76 clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}}77 clang_analyzer_eval(a3.s1[3] == 'd'); // expected-warning{{UNKNOWN}}78 clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}}79 clang_analyzer_eval(a3.s2 == 0); // expected-warning{{UNKNOWN}}80 free(a3.s2); // no warning81 return 0;82}83 84struct bb {85 struct aa a;86 char * s2;87};88 89int f4(void) {90 struct bb b0 = {{1, 2, 3, 4}, 0};91 b0.s2 = strdup("hello");92 b0.a.s2 = strdup("hola");93 char input[] = {'a', 'b', 'c', 'd'};94 char * dest = (char*)(b0.a.s1);95 memcpy(dest, input, 4);96 clang_analyzer_eval(b0.a.s1[0] == 'a'); // expected-warning{{UNKNOWN}}97 clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}}98 clang_analyzer_eval(b0.a.s1[1] == 'b'); // expected-warning{{UNKNOWN}}99 clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}}100 clang_analyzer_eval(b0.a.s1[2] == 'c'); // expected-warning{{UNKNOWN}}101 clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}}102 clang_analyzer_eval(b0.a.s1[3] == 'd'); // expected-warning{{UNKNOWN}}103 clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}}104 clang_analyzer_eval(b0.s2 == 0); // expected-warning{{UNKNOWN}}105 free(b0.a.s2); // no warning106 free(b0.s2); // no warning107 return 0;108}109 110// Test that memory leaks are caught.111int f5(void) {112 struct aa a0 = {{1, 2, 3, 4}, 0};113 a0.s2 = strdup("hello");114 char input[] = {'a', 'b', 'c', 'd'};115 memcpy(a0.s1, input, 4);116 return 0; // expected-warning{{Potential leak of memory pointed to by 'a0.s2'}}117}118 119int f6(void) {120 struct aa a1;121 a1.s2 = strdup("hello");122 char input[] = {'a', 'b', 'c', 'd'};123 memcpy(a1.s1, input, 4);124 return 0; // expected-warning{{Potential leak of memory pointed to by 'a1.s2'}}125}126 127int f7(void) {128 struct aa a2 = {{1, 2}};129 a2.s2 = strdup("hello");130 char input[] = {'a', 'b', 'c', 'd'};131 memcpy(a2.s1, input, 4);132 return 0; // expected-warning{{Potential leak of memory pointed to by 'a2.s2'}}133}134 135int f8(void) {136 struct aa a3 = {{1, 2, 3, 4}, 0};137 a3.s2 = strdup("hello");138 char input[] = {'a', 'b', 'c', 'd'};139 int * dest = (int*)a3.s1;140 memcpy(dest, input, 4);141 return 0; // expected-warning{{Potential leak of memory pointed to by 'a3.s2'}}142}143 144int f9(void) {145 struct bb b0 = {{1, 2, 3, 4}, 0};146 b0.s2 = strdup("hello");147 b0.a.s2 = strdup("hola");148 char input[] = {'a', 'b', 'c', 'd'};149 char * dest = (char*)(b0.a.s1);150 memcpy(dest, input, 4);151 free(b0.a.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.s2'}}152 return 0;153}154 155int f10(void) {156 struct bb b0 = {{1, 2, 3, 4}, 0};157 b0.s2 = strdup("hello");158 b0.a.s2 = strdup("hola");159 char input[] = {'a', 'b', 'c', 'd'};160 char * dest = (char*)(b0.a.s1);161 memcpy(dest, input, 4);162 free(b0.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.a.s2'}}163 return 0;164}165 166// Test invalidating fields being addresses of array.167struct cc {168 char * s1;169 char * s2;170};171 172int f11(void) {173 char x[4] = {1, 2};174 x[0] = 1;175 x[1] = 2;176 struct cc c0;177 c0.s2 = strdup("hello");178 c0.s1 = &x[0];179 char input[] = {'a', 'b', 'c', 'd'};180 memcpy(c0.s1, input, 4);181 clang_analyzer_eval(x[0] == 1); // expected-warning{{UNKNOWN}}182 clang_analyzer_eval(x[1] == 2); // expected-warning{{UNKNOWN}}183 clang_analyzer_eval(c0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}184 clang_analyzer_eval(c0.s1[1] == 'b'); // expected-warning{{UNKNOWN}}185 clang_analyzer_eval(c0.s1[2] == 'c'); // expected-warning{{UNKNOWN}}186 clang_analyzer_eval(c0.s1[3] == 'd'); // expected-warning{{UNKNOWN}}187 free(c0.s2); // no-warning188 return 0;189}190 191// Test inverting field position between s1 and s2.192struct dd {193 char *s2;194 char s1[4];195};196 197int f12(void) {198 struct dd d0 = {0, {1, 2, 3, 4}};199 d0.s2 = strdup("hello");200 char input[] = {'a', 'b', 'c', 'd'};201 memcpy(d0.s1, input, 4);202 clang_analyzer_eval(d0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}203 clang_analyzer_eval(d0.s1[1] == 'b'); // expected-warning{{UNKNOWN}}204 clang_analyzer_eval(d0.s1[2] == 'c'); // expected-warning{{UNKNOWN}}205 clang_analyzer_eval(d0.s1[3] == 'd'); // expected-warning{{UNKNOWN}}206 clang_analyzer_eval(d0.s2 == 0); // expected-warning{{UNKNOWN}}207 free(d0.s2); // no warning208 return 0;209}210 211// Test arrays of structs.212struct ee {213 int a;214 char b;215};216 217struct EE {218 struct ee s1[2];219 char * s2;220};221 222int f13(void) {223 struct EE E0 = {{{1, 2}, {3, 4}}, 0};224 E0.s2 = strdup("hello");225 char input[] = {'a', 'b', 'c', 'd'};226 memcpy(E0.s1, input, 4);227 clang_analyzer_eval(E0.s1[0].a == 'a'); // expected-warning{{UNKNOWN}}228 clang_analyzer_eval(E0.s1[0].b == 'b'); // expected-warning{{UNKNOWN}}229 clang_analyzer_eval(E0.s1[1].a == 'c'); // expected-warning{{UNKNOWN}}230 clang_analyzer_eval(E0.s1[1].b == 'd'); // expected-warning{{UNKNOWN}}231 clang_analyzer_eval(E0.s2 == 0); // expected-warning{{UNKNOWN}}232 free(E0.s2); // no warning233 return 0;234}235 236// Test global parameters.237struct aa a15 = {{1, 2, 3, 4}, 0};238 239int f15(void) {240 a15.s2 = strdup("hello");241 char input[] = {'a', 'b', 'c', 'd'};242 memcpy(a15.s1, input, 4);243 clang_analyzer_eval(a15.s1[0] == 'a'); // expected-warning{{UNKNOWN}}244 clang_analyzer_eval(a15.s1[1] == 'b'); // expected-warning{{UNKNOWN}}245 clang_analyzer_eval(a15.s1[2] == 'c'); // expected-warning{{UNKNOWN}}246 clang_analyzer_eval(a15.s1[3] == 'd'); // expected-warning{{UNKNOWN}}247 clang_analyzer_eval(a15.s2 == 0); // expected-warning{{UNKNOWN}}248 free(a15.s2); // no warning249 return 0;250}251 252// Test array of 0 sized elements.253struct empty {};254struct gg {255 struct empty s1[4];256 char * s2;257};258 259int f16(void) {260 struct gg g0 = {{}, 0};261 g0.s2 = strdup("hello");262 char input[] = {'a', 'b', 'c', 'd'};263 memcpy(g0.s1, input, 4);264 clang_analyzer_eval(*(int*)(&g0.s1[0]) == 'a'); // expected-warning{{UNKNOWN}}\265 expected-warning{{Potential leak of memory pointed to by 'g0.s2'}}266 clang_analyzer_eval(*(int*)(&g0.s1[1]) == 'b'); // expected-warning{{UNKNOWN}}267 clang_analyzer_eval(*(int*)(&g0.s1[2]) == 'c'); // expected-warning{{UNKNOWN}}268 clang_analyzer_eval(*(int*)(&g0.s1[3]) == 'd'); // expected-warning{{UNKNOWN}}269 clang_analyzer_eval(g0.s2 == 0); // expected-warning{{UNKNOWN}}270 free(g0.s2); // no warning271 return 0;272}273 274// Test array of 0 elements.275struct hh {276 char s1[0];277 char * s2;278};279 280int f17(void) {281 struct hh h0;282 h0.s2 = strdup("hello");283 char input[] = {'a', 'b', 'c', 'd'};284 memcpy(h0.s1, input, 4);285 clang_analyzer_eval(h0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}\286 expected-warning{{Potential leak of memory pointed to by 'h0.s2'}}287 clang_analyzer_eval(h0.s2 == 0); // expected-warning{{UNKNOWN}}288 free(h0.s2); // no warning289 return 0;290}291 292// Test writing past the array.293struct ii {294 char s1[4];295 int i;296 int j;297 char * s2;298};299 300int f18(void) {301 struct ii i18 = {{1, 2, 3, 4}, 5, 6};302 i18.i = 10;303 i18.j = 11;304 i18.s2 = strdup("hello");305 char input[100] = {3};306 memcpy(i18.s1, input, 100); // expected-warning {{'memcpy' will always overflow; destination buffer has size 24, but size argument is 100}}307 clang_analyzer_eval(i18.s1[0] == 1); // expected-warning{{UNKNOWN}}\308 expected-warning{{Potential leak of memory pointed to by 'i18.s2'}}309 clang_analyzer_eval(i18.s1[1] == 2); // expected-warning{{UNKNOWN}}310 clang_analyzer_eval(i18.s1[2] == 3); // expected-warning{{UNKNOWN}}311 clang_analyzer_eval(i18.s1[3] == 4); // expected-warning{{UNKNOWN}}312 clang_analyzer_eval(i18.i == 10); // expected-warning{{UNKNOWN}}313 clang_analyzer_eval(i18.j == 11); // expected-warning{{UNKNOWN}}314 return 0;315}316 317int f181(void) {318 struct ii i181 = {{1, 2, 3, 4}, 5, 6};319 i181.i = 10;320 i181.j = 11;321 i181.s2 = strdup("hello");322 char input[100] = {3};323 memcpy(i181.s1, input, 5); // invalidate the whole region of i181324 clang_analyzer_eval(i181.s1[0] == 1); // expected-warning{{UNKNOWN}}\325 expected-warning{{Potential leak of memory pointed to by 'i181.s2'}}326 clang_analyzer_eval(i181.s1[1] == 2); // expected-warning{{UNKNOWN}}327 clang_analyzer_eval(i181.s1[2] == 3); // expected-warning{{UNKNOWN}}328 clang_analyzer_eval(i181.s1[3] == 4); // expected-warning{{UNKNOWN}}329 clang_analyzer_eval(i181.i == 10); // expected-warning{{UNKNOWN}}330 clang_analyzer_eval(i181.j == 11); // expected-warning{{UNKNOWN}}331 return 0;332}333 334// Test array with a symbolic offset.335struct jj {336 char s1[2];337 char * s2;338};339 340struct JJ {341 struct jj s1[3];342 char * s2;343};344 345int f19(int i) {346 struct JJ J0 = {{{1, 2, 0}, {3, 4, 0}, {5, 6, 0}}, 0};347 J0.s2 = strdup("hello");348 J0.s1[0].s2 = strdup("hello");349 J0.s1[1].s2 = strdup("hi");350 J0.s1[2].s2 = strdup("world");351 char input[2] = {'a', 'b'};352 memcpy(J0.s1[i].s1, input, 2);353 clang_analyzer_eval(J0.s1[0].s1[0] == 1); // expected-warning{{UNKNOWN}}\354 expected-warning{{Potential leak of memory pointed to by field 's2'}}\355 expected-warning{{Potential leak of memory pointed to by field 's2'}}\356 expected-warning{{Potential leak of memory pointed to by field 's2'}}\357 expected-warning{{Potential leak of memory pointed to by 'J0.s2'}}358 clang_analyzer_eval(J0.s1[0].s1[1] == 2); // expected-warning{{UNKNOWN}}359 clang_analyzer_eval(J0.s1[1].s1[0] == 3); // expected-warning{{UNKNOWN}}360 clang_analyzer_eval(J0.s1[1].s1[1] == 4); // expected-warning{{UNKNOWN}}361 clang_analyzer_eval(J0.s1[2].s1[0] == 5); // expected-warning{{UNKNOWN}}362 clang_analyzer_eval(J0.s1[2].s1[1] == 6); // expected-warning{{UNKNOWN}}363 clang_analyzer_eval(J0.s1[i].s1[0] == 5); // expected-warning{{UNKNOWN}}364 clang_analyzer_eval(J0.s1[i].s1[1] == 6); // expected-warning{{UNKNOWN}}365 // FIXME: memory leak warning for J0.s2 should be emitted here instead of after memcpy call.366 return 0; // no warning367}368 369// Test array with its super region having symbolic offseted regions.370int f20(int i) {371 struct aa * a20 = malloc(sizeof(struct aa) * 2);372 a20[0].s1[0] = 1;373 a20[0].s1[1] = 2;374 a20[0].s1[2] = 3;375 a20[0].s1[3] = 4;376 a20[0].s2 = strdup("hello");377 a20[1].s1[0] = 5;378 a20[1].s1[1] = 6;379 a20[1].s1[2] = 7;380 a20[1].s1[3] = 8;381 a20[1].s2 = strdup("world");382 a20[i].s2 = strdup("hola");383 char input[] = {'a', 'b', 'c', 'd'};384 memcpy(a20[0].s1, input, 4);385 clang_analyzer_eval(a20[0].s1[0] == 1); // expected-warning{{UNKNOWN}}386 clang_analyzer_eval(a20[0].s1[1] == 1); // expected-warning{{UNKNOWN}}387 clang_analyzer_eval(a20[0].s1[2] == 1); // expected-warning{{UNKNOWN}}388 clang_analyzer_eval(a20[0].s1[3] == 1); // expected-warning{{UNKNOWN}}389 clang_analyzer_eval(a20[0].s2 == 0); // expected-warning{{UNKNOWN}}390 clang_analyzer_eval(a20[1].s1[0] == 1); // expected-warning{{UNKNOWN}}391 clang_analyzer_eval(a20[1].s1[1] == 1); // expected-warning{{UNKNOWN}}392 clang_analyzer_eval(a20[1].s1[2] == 1); // expected-warning{{UNKNOWN}}393 clang_analyzer_eval(a20[1].s1[3] == 1); // expected-warning{{UNKNOWN}}394 clang_analyzer_eval(a20[1].s2 == 0); // expected-warning{{UNKNOWN}}395 clang_analyzer_eval(a20[i].s1[0] == 1); // expected-warning{{UNKNOWN}}396 clang_analyzer_eval(a20[i].s1[1] == 1); // expected-warning{{UNKNOWN}}397 clang_analyzer_eval(a20[i].s1[2] == 1); // expected-warning{{UNKNOWN}}398 clang_analyzer_eval(a20[i].s1[3] == 1); // expected-warning{{UNKNOWN}}399 clang_analyzer_eval(a20[i].s2 == 0); // expected-warning{{UNKNOWN}}\400 expected-warning{{Potential leak of memory pointed to by 'a20'}}401 402 return 0;403}404 405// Test array's region and super region both having symbolic offsets.406int f21(int i) {407 struct aa * a21 = malloc(sizeof(struct aa) * 2);408 a21[0].s1[0] = 1;409 a21[0].s1[1] = 2;410 a21[0].s1[2] = 3;411 a21[0].s1[3] = 4;412 a21[0].s2 = 0;413 a21[1].s1[0] = 5;414 a21[1].s1[1] = 6;415 a21[1].s1[2] = 7;416 a21[1].s1[3] = 8;417 a21[1].s2 = 0;418 a21[i].s2 = strdup("hello");419 a21[i].s1[0] = 1;420 a21[i].s1[1] = 2;421 a21[i].s1[2] = 3;422 a21[i].s1[3] = 4;423 char input[] = {'a', 'b', 'c', 'd'};424 memcpy(a21[i].s1, input, 4);425 clang_analyzer_eval(a21[0].s1[0] == 1); // expected-warning{{UNKNOWN}}426 clang_analyzer_eval(a21[0].s1[1] == 1); // expected-warning{{UNKNOWN}}427 clang_analyzer_eval(a21[0].s1[2] == 1); // expected-warning{{UNKNOWN}}428 clang_analyzer_eval(a21[0].s1[3] == 1); // expected-warning{{UNKNOWN}}429 clang_analyzer_eval(a21[0].s2 == 0); // expected-warning{{UNKNOWN}}430 clang_analyzer_eval(a21[1].s1[0] == 1); // expected-warning{{UNKNOWN}}431 clang_analyzer_eval(a21[1].s1[1] == 1); // expected-warning{{UNKNOWN}}432 clang_analyzer_eval(a21[1].s1[2] == 1); // expected-warning{{UNKNOWN}}433 clang_analyzer_eval(a21[1].s1[3] == 1); // expected-warning{{UNKNOWN}}434 clang_analyzer_eval(a21[1].s2 == 0); // expected-warning{{UNKNOWN}}435 clang_analyzer_eval(a21[i].s1[0] == 1); // expected-warning{{UNKNOWN}}436 clang_analyzer_eval(a21[i].s1[1] == 1); // expected-warning{{UNKNOWN}}437 clang_analyzer_eval(a21[i].s1[2] == 1); // expected-warning{{UNKNOWN}}438 clang_analyzer_eval(a21[i].s1[3] == 1); // expected-warning{{UNKNOWN}}439 clang_analyzer_eval(a21[i].s2 == 0); // expected-warning{{UNKNOWN}}\440 expected-warning{{Potential leak of memory pointed to by 'a21'}}441 442 return 0;443}444 445// Test regions aliasing other regions.446struct ll {447 char s1[4];448 char * s2;449};450 451struct mm {452 char s3[4];453 char * s4;454};455 456int f24(void) {457 struct ll l24 = {{1, 2, 3, 4}, 0};458 struct mm * m24 = (struct mm *)&l24;459 m24->s4 = strdup("hello");460 char input[] = {1, 2, 3, 4};461 memcpy(m24->s3, input, 4);462 clang_analyzer_eval(m24->s3[0] == 1); // expected-warning{{UNKNOWN}}463 clang_analyzer_eval(m24->s3[1] == 1); // expected-warning{{UNKNOWN}}464 clang_analyzer_eval(m24->s3[2] == 1); // expected-warning{{UNKNOWN}}465 clang_analyzer_eval(m24->s3[3] == 1); // expected-warning{{UNKNOWN}}466 clang_analyzer_eval(l24.s1[0] == 1); // expected-warning{{UNKNOWN}}467 clang_analyzer_eval(l24.s1[1] == 1); // expected-warning{{UNKNOWN}}468 clang_analyzer_eval(l24.s1[2] == 1); // expected-warning{{UNKNOWN}}469 clang_analyzer_eval(l24.s1[3] == 1); // expected-warning{{UNKNOWN}}\470 expected-warning{{Potential leak of memory pointed to by field 's4'}}471 return 0;472}473 474// Test region with potential aliasing and symbolic offsets.475// Store assumes no aliasing.476int f25(int i, int j, struct ll * l, struct mm * m) {477 m->s4 = strdup("hola"); // m->s4 not tracked478 m->s3[0] = 1;479 m->s3[1] = 2;480 m->s3[2] = 3;481 m->s3[3] = 4;482 m->s3[j] = 5; // invalidates m->s3483 l->s2 = strdup("hello"); // l->s2 not tracked484 l->s1[0] = 6;485 l->s1[1] = 7;486 l->s1[2] = 8;487 l->s1[3] = 9;488 l->s1[i] = 10; // invalidates l->s1489 char input[] = {1, 2, 3, 4};490 memcpy(m->s3, input, 4); // does not invalidate l->s1[i]491 clang_analyzer_eval(m->s3[0] == 1); // expected-warning{{UNKNOWN}}492 clang_analyzer_eval(m->s3[1] == 1); // expected-warning{{UNKNOWN}}493 clang_analyzer_eval(m->s3[2] == 1); // expected-warning{{UNKNOWN}}494 clang_analyzer_eval(m->s3[3] == 1); // expected-warning{{UNKNOWN}}495 clang_analyzer_eval(m->s3[i] == 1); // expected-warning{{UNKNOWN}}496 clang_analyzer_eval(m->s3[j] == 1); // expected-warning{{UNKNOWN}}497 clang_analyzer_eval(l->s1[0] == 1); // expected-warning{{UNKNOWN}}498 clang_analyzer_eval(l->s1[1] == 1); // expected-warning{{UNKNOWN}}499 clang_analyzer_eval(l->s1[2] == 1); // expected-warning{{UNKNOWN}}500 clang_analyzer_eval(l->s1[3] == 1); // expected-warning{{UNKNOWN}}501 clang_analyzer_eval(l->s1[i] == 1); // expected-warning{{FALSE}}502 clang_analyzer_eval(l->s1[j] == 1); // expected-warning{{UNKNOWN}}503 return 0;504}505 506// Test size with symbolic size argument.507int f26(int i) {508 struct aa a26 = {{1, 2, 3, 4}, 0};509 a26.s2 = strdup("hello");510 char input[] = {'a', 'b', 'c', 'd'};511 memcpy(a26.s1, input, i); // i assumed in bound512 clang_analyzer_eval(a26.s1[0] == 1); // expected-warning{{UNKNOWN}}513 clang_analyzer_eval(a26.s1[1] == 1); // expected-warning{{UNKNOWN}}514 clang_analyzer_eval(a26.s1[2] == 1); // expected-warning{{UNKNOWN}}515 clang_analyzer_eval(a26.s1[3] == 1); // expected-warning{{UNKNOWN}}\516 expected-warning{{Potential leak of memory pointed to by 'a26.s2'}}517 return 0;518}519 520// Test sizeof as a size argument.521int f261(void) {522 struct aa a261 = {{1, 2, 3, 4}, 0};523 a261.s2 = strdup("hello");524 char input[] = {'a', 'b', 'c', 'd'};525 memcpy(a261.s1, input, sizeof(a261.s1));526 clang_analyzer_eval(a261.s1[0] == 1); // expected-warning{{UNKNOWN}}527 clang_analyzer_eval(a261.s1[1] == 1); // expected-warning{{UNKNOWN}}528 clang_analyzer_eval(a261.s1[2] == 1); // expected-warning{{UNKNOWN}}529 clang_analyzer_eval(a261.s1[3] == 1); // expected-warning{{UNKNOWN}}\530 expected-warning{{Potential leak of memory pointed to by 'a261.s2'}}531 return 0;532}533 534// Test negative size argument.535int f262(void) {536 struct aa a262 = {{1, 2, 3, 4}, 0};537 a262.s2 = strdup("hello");538 char input[] = {'a', 'b', 'c', 'd'};539 memcpy(a262.s1, input, -1); // expected-warning{{'memcpy' will always overflow; destination buffer has size 16, but size argument is 18446744073709551615}}540 clang_analyzer_eval(a262.s1[0] == 1); // expected-warning{{UNKNOWN}}\541 expected-warning{{Potential leak of memory pointed to by 'a262.s2'}}542 clang_analyzer_eval(a262.s1[1] == 1); // expected-warning{{UNKNOWN}}543 clang_analyzer_eval(a262.s1[2] == 1); // expected-warning{{UNKNOWN}}544 clang_analyzer_eval(a262.s1[3] == 1); // expected-warning{{UNKNOWN}}545 return 0;546}547 548// Test size argument being an unknown value.549struct xx {550 char s1[4];551 char * s2;552};553 554int f263(int n, char * len) {555 struct xx x263 = {0};556 x263.s2 = strdup("hello");557 char input[] = {'a', 'b', 'c', 'd'};558 memcpy(x263.s1, input, *(len + n));559 clang_analyzer_eval(x263.s1[0] == 0); // expected-warning{{UNKNOWN}}\560 expected-warning{{Potential leak of memory pointed to by 'x263.s2'}}561 clang_analyzer_eval(x263.s1[1] == 0); // expected-warning{{UNKNOWN}}562 clang_analyzer_eval(x263.s1[2] == 0); // expected-warning{{UNKNOWN}}563 clang_analyzer_eval(x263.s1[3] == 0); // expected-warning{{UNKNOWN}}564 clang_analyzer_eval(x263.s2 == 0); // expected-warning{{UNKNOWN}}565 return 0;566}567 568 569// Test casting regions with symbolic offseted sub regions.570int f27(int i) {571 struct mm m27 = {{1, 2, 3, 4}, 0};572 m27.s4 = strdup("hello");573 m27.s3[i] = 5;574 char input[] = {'a', 'b', 'c', 'd'};575 memcpy(((struct ll*)(&m27))->s1, input, 4);576 clang_analyzer_eval(m27.s3[0] == 1); // expected-warning{{UNKNOWN}}577 clang_analyzer_eval(m27.s3[1] == 1); // expected-warning{{UNKNOWN}}578 clang_analyzer_eval(m27.s3[2] == 1); // expected-warning{{UNKNOWN}}579 clang_analyzer_eval(m27.s3[3] == 1); // expected-warning{{UNKNOWN}}580 clang_analyzer_eval(m27.s3[i] == 1); // expected-warning{{UNKNOWN}}\581 expected-warning{{Potential leak of memory pointed to by 'm27.s4'}}582 return 0;583}584 585int f28(int i, int j, int k, int l) {586 struct mm m28[2];587 m28[i].s4 = strdup("hello");588 m28[j].s3[k] = 1;589 struct ll * l28 = (struct ll*)(&m28[1]);590 l28->s1[l] = 2;591 char input[] = {'a', 'b', 'c', 'd'}; // expected-warning{{Potential leak of memory pointed to by field 's4'}}592 memcpy(l28->s1, input, 4);593 clang_analyzer_eval(m28[0].s3[0] == 1); // expected-warning{{UNKNOWN}}594 clang_analyzer_eval(m28[0].s3[1] == 1); // expected-warning{{UNKNOWN}}595 clang_analyzer_eval(m28[0].s3[2] == 1); // expected-warning{{UNKNOWN}}596 clang_analyzer_eval(m28[0].s3[3] == 1); // expected-warning{{UNKNOWN}}597 clang_analyzer_eval(m28[1].s3[0] == 1); // expected-warning{{UNKNOWN}}598 clang_analyzer_eval(m28[1].s3[1] == 1); // expected-warning{{UNKNOWN}}599 clang_analyzer_eval(m28[1].s3[2] == 1); // expected-warning{{UNKNOWN}}600 clang_analyzer_eval(m28[1].s3[3] == 1); // expected-warning{{UNKNOWN}}601 clang_analyzer_eval(m28[i].s3[0] == 1); // expected-warning{{UNKNOWN}}602 clang_analyzer_eval(m28[i].s3[1] == 1); // expected-warning{{UNKNOWN}}603 clang_analyzer_eval(m28[i].s3[2] == 1); // expected-warning{{UNKNOWN}}604 clang_analyzer_eval(m28[i].s3[3] == 1); // expected-warning{{UNKNOWN}}605 clang_analyzer_eval(m28[j].s3[k] == 1); // expected-warning{{UNKNOWN}}606 clang_analyzer_eval(l28->s1[l] == 2); // expected-warning{{UNKNOWN}}607 return 0;608}609 610int f29(int i, int j, int k, int l, int m) {611 struct mm m29[2];612 m29[i].s4 = strdup("hello");613 m29[j].s3[k] = 1;614 struct ll * l29 = (struct ll*)(&m29[l]);615 l29->s1[m] = 2;616 char input[] = {'a', 'b', 'c', 'd'};617 memcpy(l29->s1, input, 4);618 clang_analyzer_eval(m29[0].s3[0] == 1); // expected-warning{{UNKNOWN}}619 clang_analyzer_eval(m29[0].s3[1] == 1); // expected-warning{{UNKNOWN}}620 clang_analyzer_eval(m29[0].s3[2] == 1); // expected-warning{{UNKNOWN}}621 clang_analyzer_eval(m29[0].s3[3] == 1); // expected-warning{{UNKNOWN}}622 clang_analyzer_eval(m29[1].s3[0] == 1); // expected-warning{{UNKNOWN}}623 clang_analyzer_eval(m29[1].s3[1] == 1); // expected-warning{{UNKNOWN}}624 clang_analyzer_eval(m29[1].s3[2] == 1); // expected-warning{{UNKNOWN}}625 clang_analyzer_eval(m29[1].s3[3] == 1); // expected-warning{{UNKNOWN}}626 clang_analyzer_eval(m29[i].s3[0] == 1); // expected-warning{{UNKNOWN}}627 clang_analyzer_eval(m29[i].s3[1] == 1); // expected-warning{{UNKNOWN}}628 clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}}629 clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}}630 clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}}631 clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}}632 // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line,633 // because l29 and m29 alias.634 return 0;635}636 637// Test unions' fields.638union uu {639 char x;640 char s1[4];641};642 643int f30(void) {644 union uu u30 = { .s1 = {1, 2, 3, 4}};645 char input[] = {1, 2, 3, 4};646 memcpy(u30.s1, input, 4);647 clang_analyzer_eval(u30.s1[0] == 1); // expected-warning{{UNKNOWN}}648 clang_analyzer_eval(u30.s1[1] == 1); // expected-warning{{UNKNOWN}}649 clang_analyzer_eval(u30.s1[2] == 1); // expected-warning{{UNKNOWN}}650 clang_analyzer_eval(u30.s1[3] == 1); // expected-warning{{UNKNOWN}}651 clang_analyzer_eval(u30.x == 1); // expected-warning{{UNKNOWN}}652 return 0;653}654 655struct kk {656 union uu u;657 char * s2;658};659 660int f31(void) {661 struct kk k31;662 k31.s2 = strdup("hello");663 k31.u.x = 1;664 char input[] = {'a', 'b', 'c', 'd'};665 memcpy(k31.u.s1, input, 4);666 clang_analyzer_eval(k31.u.s1[0] == 1); // expected-warning{{UNKNOWN}}\667 expected-warning{{Potential leak of memory pointed to by 'k31.s2'}}668 clang_analyzer_eval(k31.u.s1[1] == 1); // expected-warning{{UNKNOWN}}669 clang_analyzer_eval(k31.u.s1[2] == 1); // expected-warning{{UNKNOWN}}670 clang_analyzer_eval(k31.u.s1[3] == 1); // expected-warning{{UNKNOWN}}671 clang_analyzer_eval(k31.u.x == 1); // expected-warning{{UNKNOWN}}672 // FIXME: memory leak warning for k31.s2 should be emitted here.673 return 0;674}675 676union vv {677 int x;678 char * s2;679};680 681int f32(void) {682 union vv v32;683 v32.s2 = strdup("hello");684 char input[] = {'a', 'b', 'c', 'd'};685 memcpy(v32.s2, input, 4);686 clang_analyzer_eval(v32.s2[0] == 1); // expected-warning{{UNKNOWN}}687 clang_analyzer_eval(v32.s2[1] == 1); // expected-warning{{UNKNOWN}}688 clang_analyzer_eval(v32.s2[2] == 1); // expected-warning{{UNKNOWN}}689 clang_analyzer_eval(v32.s2[3] == 1); // expected-warning{{UNKNOWN}}\690 expected-warning{{Potential leak of memory pointed to by 'v32.s2'}}691 return 0;692}693 694struct nn {695 int s1;696 int i;697 int j;698 int k;699 char * s2;700};701 702// Test bad types to dest buffer.703int f33(void) {704 struct nn n33 = {1, 2, 3, 4, 0};705 n33.s2 = strdup("hello");706 char input[] = {'a', 'b', 'c', 'd'};707 memcpy(n33.s1, input, 4); // expected-warning{{incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'}}708 clang_analyzer_eval(n33.i == 2); // expected-warning{{TRUE}}709 clang_analyzer_eval(n33.j == 3); // expected-warning{{TRUE}}710 clang_analyzer_eval(n33.k == 4); // expected-warning{{TRUE}}711 clang_analyzer_eval(((char*)(n33.s1))[0] == 1); // expected-warning{{UNKNOWN}}\712 expected-warning{{cast to 'char *' from smaller integer type 'int'}}713 clang_analyzer_eval(((char*)(n33.s1))[1] == 1); // expected-warning{{UNKNOWN}}\714 expected-warning{{cast to 'char *' from smaller integer type 'int'}}715 clang_analyzer_eval(((char*)(n33.s1))[2] == 1); // expected-warning{{UNKNOWN}}\716 expected-warning{{cast to 'char *' from smaller integer type 'int'}}717 clang_analyzer_eval(((char*)(n33.s1))[3] == 1); // expected-warning{{UNKNOWN}}\718 expected-warning{{cast to 'char *' from smaller integer type 'int'}}719 clang_analyzer_eval(n33.s2 == 0); //expected-warning{{UNKNOWN}}720 return 0; // expected-warning{{Potential leak of memory pointed to by 'n33.s2'}}721}722 723// Test destination buffer being an unknown value.724struct ww {725 int s1[4];726 char s2;727};728 729int f34(struct ww * w34, int n) {730 w34->s2 = 3;731 char input[] = {'a', 'b', 'c', 'd'};732 memcpy(w34->s1 + n, input , 4);733 clang_analyzer_eval(w34->s1[0] == 0); // expected-warning{{UNKNOWN}}734 clang_analyzer_eval(w34->s1[1] == 0); // expected-warning{{UNKNOWN}}735 clang_analyzer_eval(w34->s1[2] == 0); // expected-warning{{UNKNOWN}}736 clang_analyzer_eval(w34->s1[3] == 0); // expected-warning{{UNKNOWN}}737 clang_analyzer_eval(w34->s1[n] == 0); // expected-warning{{UNKNOWN}}738 clang_analyzer_eval(w34->s2 == 3); // expected-warning{{TRUE}}739 return 0;740}741 742// Test dest buffer as an element region with a symbolic index and size parameter as a symbolic value.743struct yy {744 char s1[4];745 char * s2;746};747 748int f35(int i, int n) {749 struct yy y35 = {{1, 2, 3, 4}, 0};750 y35.s2 = strdup("hello");751 char input[] = {'a', 'b', 'c', 'd'};752 memcpy(&(y35.s1[i]), input, n);753 clang_analyzer_eval(y35.s1[0] == 0); // expected-warning{{UNKNOWN}}754 clang_analyzer_eval(y35.s1[1] == 0); // expected-warning{{UNKNOWN}}755 clang_analyzer_eval(y35.s1[2] == 0); // expected-warning{{UNKNOWN}}756 clang_analyzer_eval(y35.s1[3] == 0); // expected-warning{{UNKNOWN}}757 clang_analyzer_eval(y35.s1[i] == 0); // expected-warning{{UNKNOWN}}758 clang_analyzer_eval(y35.s2 == 0); // expected-warning{{UNKNOWN}}759 return 0; // expected-warning{{Potential leak of memory pointed to by 'y35.s2'}}760}761 762// Test regions with negative offsets.763struct zz {764 char s1[4];765 int s2;766};767 768int f36(struct zz * z36) {769 770 char input[] = {'a', 'b', 'c', 'd'};771 z36->s1[0] = 0;772 z36->s1[1] = 1;773 z36->s1[2] = 2;774 z36->s1[3] = 3;775 z36->s2 = 10;776 777 z36 = z36 - 1; // Decrement by 8 bytes (struct zz is 8 bytes).778 779 z36->s1[0] = 4;780 z36->s1[1] = 5;781 z36->s1[2] = 6;782 z36->s1[3] = 7;783 z36->s2 = 11;784 785 memcpy(z36->s1, input, 4);786 787 clang_analyzer_eval(z36->s1[0] == 1); // expected-warning{{UNKNOWN}}788 clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{UNKNOWN}}789 clang_analyzer_eval(z36->s1[2] == 1); // expected-warning{{UNKNOWN}}790 clang_analyzer_eval(z36->s1[3] == 1); // expected-warning{{UNKNOWN}}791 clang_analyzer_eval(z36->s2 == 11); // expected-warning{{TRUE}}792 793 z36 = z36 + 1; // Increment back.794 795 clang_analyzer_eval(z36->s1[0] == 0); // expected-warning{{TRUE}}796 clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{TRUE}}797 clang_analyzer_eval(z36->s1[2] == 2); // expected-warning{{TRUE}}798 clang_analyzer_eval(z36->s1[3] == 3); // expected-warning{{TRUE}}799 clang_analyzer_eval(z36->s2 == 10); // expected-warning{{TRUE}}800 801 return 0;802}803 804int f37(struct zz * z37) {805 806 char input[] = {'a', 'b', 'c', 'd'};807 z37->s1[0] = 0;808 z37->s1[1] = 1;809 z37->s1[2] = 2;810 z37->s1[3] = 3;811 z37->s2 = 10;812 813 z37 = (struct zz *)((char*)(z37) - 4); // Decrement by 4 bytes (struct zz is 8 bytes).814 815 z37->s1[0] = 4;816 z37->s1[1] = 5;817 z37->s1[2] = 6;818 z37->s1[3] = 7;819 z37->s2 = 11;820 821 memcpy(z37->s1, input, 4);822 823 clang_analyzer_eval(z37->s1[0] == 1); // expected-warning{{UNKNOWN}}824 clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}}825 clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}}826 clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}}827 clang_analyzer_eval(z37->s2 == 11); // expected-warning{{TRUE}}828 829 z37 = (struct zz *)((char*)(z37) + 4); // Increment back.830 831 clang_analyzer_eval(z37->s1[0] == 11); // expected-warning{{TRUE}}832 clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}}833 clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}}834 clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}}835 clang_analyzer_eval(z37->s2 == 10); // expected-warning{{TRUE}}836 837 return 0;838}839 840int f38(struct zz * z38) {841 842 char input[] = {'a', 'b', 'c', 'd'};843 z38->s1[0] = 0;844 z38->s1[1] = 1;845 z38->s1[2] = 2;846 z38->s1[3] = 3;847 z38->s2 = 10;848 849 z38 = (struct zz *)((char*)(z38) - 2); // Decrement by 2 bytes (struct zz is 8 bytes).850 851 z38->s1[0] = 4;852 z38->s1[1] = 5;853 z38->s1[2] = 6;854 z38->s1[3] = 7;855 z38->s2 = 11;856 857 memcpy(z38->s1, input, 4);858 859 clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}}860 clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}}861 clang_analyzer_eval(z38->s1[2] == 1); // expected-warning{{UNKNOWN}}862 clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}}863 clang_analyzer_eval(z38->s2 == 11); // expected-warning{{TRUE}}864 865 z38 = (struct zz *)((char*)(z38) + 2); // Increment back.866 867 clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}}868 clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}}869 clang_analyzer_eval(z38->s1[2] == 11); // expected-warning{{TRUE}}870 clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}}871 clang_analyzer_eval(z38->s2 == 10); // expected-warning{{UNKNOWN}}872 873 return 0;874}875 876// Test negative offsets with a different structure layout.877struct z0 {878 int s2;879 char s1[4];880};881 882int f39(struct z0 * d39) {883 884 char input[] = {'a', 'b', 'c', 'd'};885 d39->s1[0] = 0;886 d39->s1[1] = 1;887 d39->s1[2] = 2;888 d39->s1[3] = 3;889 d39->s2 = 10;890 891 d39 = (struct z0 *)((char*)(d39) - 2); // Decrement by 2 bytes (struct z0 is 8 bytes).892 893 d39->s1[0] = 4;894 d39->s1[1] = 5;895 d39->s1[2] = 6;896 d39->s1[3] = 7;897 d39->s2 = 11;898 899 memcpy(d39->s1, input, 4);900 901 clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}}902 clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}}903 clang_analyzer_eval(d39->s1[2] == 1); // expected-warning{{UNKNOWN}}904 clang_analyzer_eval(d39->s1[3] == 1); // expected-warning{{UNKNOWN}}905 clang_analyzer_eval(d39->s2 == 11); // expected-warning{{TRUE}}906 907 d39 = (struct z0 *)((char*)(d39) + 2); // Increment back.908 909 clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}}910 clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}}911 clang_analyzer_eval(d39->s1[2] == 2); // expected-warning{{TRUE}}912 clang_analyzer_eval(d39->s1[3] == 3); // expected-warning{{TRUE}}913 // FIXME: d39->s2 should evaluate to at least UNKNOWN or FALSE,914 // 'collectSubRegionBindings(...)' in RegionStore.cpp will need to915 // handle a regions' upper boundary overflowing.916 clang_analyzer_eval(d39->s2 == 10); // expected-warning{{TRUE}}917 918 return 0;919}920 921