| // Given code 'struct aa { char s1[4]; char * s2;} a; memcpy(a.s1, ...);', |
| // this test checks that the CStringChecker only invalidates the destination buffer array a.s1 (instead of a.s1 and a.s2). |
| // At the moment the whole of the destination array content is invalidated. |
| // If a.s1 region has a symbolic offset, the whole region of 'a' is invalidated. |
| // Specific triple set to test structures of size 0. |
| // RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s |
| |
| typedef __typeof(sizeof(int)) size_t; |
| |
| char *strdup(const char *s); |
| void free(void *); |
| void *memcpy(void *dst, const void *src, size_t n); // expected-note{{passing argument to parameter 'dst' here}} |
| void *malloc(size_t n); |
| |
| void clang_analyzer_eval(int); |
| |
| struct aa { |
| char s1[4]; |
| char *s2; |
| }; |
| |
| // Test different types of structure initialisation. |
| int f0() { |
| struct aa a0 = {{1, 2, 3, 4}, 0}; |
| a0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a0.s1, input, 4); |
| clang_analyzer_eval(a0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(a0.s2); // no warning |
| return 0; |
| } |
| |
| int f1() { |
| struct aa a1; |
| a1.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a1.s1, input, 4); |
| clang_analyzer_eval(a1.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a1.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a1.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a1.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a1.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(a1.s2); // no warning |
| return 0; |
| } |
| |
| int f2() { |
| struct aa a2 = {{1, 2}}; |
| a2.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a2.s1, input, 4); |
| clang_analyzer_eval(a2.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a2.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a2.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a2.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a2.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(a2.s2); // no warning |
| return 0; |
| } |
| |
| int f3() { |
| struct aa a3 = {{1, 2, 3, 4}, 0}; |
| a3.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| int * dest = (int*)a3.s1; |
| memcpy(dest, input, 4); |
| clang_analyzer_eval(a3.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a3.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a3.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a3.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a3.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(a3.s2); // no warning |
| return 0; |
| } |
| |
| struct bb { |
| struct aa a; |
| char * s2; |
| }; |
| |
| int f4() { |
| struct bb b0 = {{1, 2, 3, 4}, 0}; |
| b0.s2 = strdup("hello"); |
| b0.a.s2 = strdup("hola"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| char * dest = (char*)(b0.a.s1); |
| memcpy(dest, input, 4); |
| clang_analyzer_eval(b0.a.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(b0.a.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(b0.a.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(b0.a.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(b0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(b0.a.s2); // no warning |
| free(b0.s2); // no warning |
| return 0; |
| } |
| |
| // Test that memory leaks are caught. |
| int f5() { |
| struct aa a0 = {{1, 2, 3, 4}, 0}; |
| a0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a0.s1, input, 4); |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'a0.s2'}} |
| } |
| |
| int f6() { |
| struct aa a1; |
| a1.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a1.s1, input, 4); |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'a1.s2'}} |
| } |
| |
| int f7() { |
| struct aa a2 = {{1, 2}}; |
| a2.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a2.s1, input, 4); |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'a2.s2'}} |
| } |
| |
| int f8() { |
| struct aa a3 = {{1, 2, 3, 4}, 0}; |
| a3.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| int * dest = (int*)a3.s1; |
| memcpy(dest, input, 4); |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'a3.s2'}} |
| } |
| |
| int f9() { |
| struct bb b0 = {{1, 2, 3, 4}, 0}; |
| b0.s2 = strdup("hello"); |
| b0.a.s2 = strdup("hola"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| char * dest = (char*)(b0.a.s1); |
| memcpy(dest, input, 4); |
| free(b0.a.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.s2'}} |
| return 0; |
| } |
| |
| int f10() { |
| struct bb b0 = {{1, 2, 3, 4}, 0}; |
| b0.s2 = strdup("hello"); |
| b0.a.s2 = strdup("hola"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| char * dest = (char*)(b0.a.s1); |
| memcpy(dest, input, 4); |
| free(b0.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.a.s2'}} |
| return 0; |
| } |
| |
| // Test invalidating fields being addresses of array. |
| struct cc { |
| char * s1; |
| char * s2; |
| }; |
| |
| int f11() { |
| char x[4] = {1, 2}; |
| x[0] = 1; |
| x[1] = 2; |
| struct cc c0; |
| c0.s2 = strdup("hello"); |
| c0.s1 = &x[0]; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(c0.s1, input, 4); |
| clang_analyzer_eval(x[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(x[1] == 2); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(c0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(c0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(c0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(c0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| free(c0.s2); // no-warning |
| return 0; |
| } |
| |
| // Test inverting field position between s1 and s2. |
| struct dd { |
| char *s2; |
| char s1[4]; |
| }; |
| |
| int f12() { |
| struct dd d0 = {0, {1, 2, 3, 4}}; |
| d0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(d0.s1, input, 4); |
| clang_analyzer_eval(d0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(d0.s2); // no warning |
| return 0; |
| } |
| |
| // Test arrays of structs. |
| struct ee { |
| int a; |
| char b; |
| }; |
| |
| struct EE { |
| struct ee s1[2]; |
| char * s2; |
| }; |
| |
| int f13() { |
| struct EE E0 = {{{1, 2}, {3, 4}}, 0}; |
| E0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(E0.s1, input, 4); |
| clang_analyzer_eval(E0.s1[0].a == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(E0.s1[0].b == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(E0.s1[1].a == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(E0.s1[1].b == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(E0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(E0.s2); // no warning |
| return 0; |
| } |
| |
| // Test global parameters. |
| struct aa a15 = {{1, 2, 3, 4}, 0}; |
| |
| int f15() { |
| a15.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a15.s1, input, 4); |
| clang_analyzer_eval(a15.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a15.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a15.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a15.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a15.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(a15.s2); // no warning |
| return 0; |
| } |
| |
| // Test array of 0 sized elements. |
| struct empty {}; |
| struct gg { |
| struct empty s1[4]; |
| char * s2; |
| }; |
| |
| int f16() { |
| struct gg g0 = {{}, 0}; |
| g0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(g0.s1, input, 4); |
| clang_analyzer_eval(*(int*)(&g0.s1[0]) == 'a'); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'g0.s2'}} |
| clang_analyzer_eval(*(int*)(&g0.s1[1]) == 'b'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(*(int*)(&g0.s1[2]) == 'c'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(*(int*)(&g0.s1[3]) == 'd'); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(g0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(g0.s2); // no warning |
| return 0; |
| } |
| |
| // Test array of 0 elements. |
| struct hh { |
| char s1[0]; |
| char * s2; |
| }; |
| |
| int f17() { |
| struct hh h0; |
| h0.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(h0.s1, input, 4); |
| clang_analyzer_eval(h0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'h0.s2'}} |
| clang_analyzer_eval(h0.s2 == 0); // expected-warning{{UNKNOWN}} |
| free(h0.s2); // no warning |
| return 0; |
| } |
| |
| // Test writing past the array. |
| struct ii { |
| char s1[4]; |
| int i; |
| int j; |
| char * s2; |
| }; |
| |
| int f18() { |
| struct ii i18 = {{1, 2, 3, 4}, 5, 6}; |
| i18.i = 10; |
| i18.j = 11; |
| i18.s2 = strdup("hello"); |
| char input[100] = {3}; |
| memcpy(i18.s1, input, 100); |
| clang_analyzer_eval(i18.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'i18.s2'}} |
| clang_analyzer_eval(i18.s1[1] == 2); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i18.s1[2] == 3); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i18.s1[3] == 4); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i18.i == 10); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i18.j == 11); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| int f181() { |
| struct ii i181 = {{1, 2, 3, 4}, 5, 6}; |
| i181.i = 10; |
| i181.j = 11; |
| i181.s2 = strdup("hello"); |
| char input[100] = {3}; |
| memcpy(i181.s1, input, 5); // invalidate the whole region of i181 |
| clang_analyzer_eval(i181.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'i181.s2'}} |
| clang_analyzer_eval(i181.s1[1] == 2); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i181.s1[2] == 3); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i181.s1[3] == 4); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i181.i == 10); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(i181.j == 11); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| // Test array with a symbolic offset. |
| struct jj { |
| char s1[2]; |
| char * s2; |
| }; |
| |
| struct JJ { |
| struct jj s1[3]; |
| char * s2; |
| }; |
| |
| int f19(int i) { |
| struct JJ J0 = {{{1, 2, 0}, {3, 4, 0}, {5, 6, 0}}, 0}; |
| J0.s2 = strdup("hello"); |
| J0.s1[0].s2 = strdup("hello"); |
| J0.s1[1].s2 = strdup("hi"); |
| J0.s1[2].s2 = strdup("world"); |
| char input[2] = {'a', 'b'}; |
| memcpy(J0.s1[i].s1, input, 2); |
| clang_analyzer_eval(J0.s1[0].s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by field 's2'}}\ |
| expected-warning{{Potential leak of memory pointed to by 'J0.s2'}} |
| clang_analyzer_eval(J0.s1[0].s1[1] == 2); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[1].s1[0] == 3); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[1].s1[1] == 4); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[2].s1[0] == 5); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[2].s1[1] == 6); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[i].s1[0] == 5); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(J0.s1[i].s1[1] == 6); // expected-warning{{UNKNOWN}} |
| // FIXME: memory leak warning for J0.s2 should be emitted here instead of after memcpy call. |
| return 0; // no warning |
| } |
| |
| // Test array with its super region having symbolic offseted regions. |
| int f20(int i) { |
| struct aa * a20 = malloc(sizeof(struct aa) * 2); |
| a20[0].s1[0] = 1; |
| a20[0].s1[1] = 2; |
| a20[0].s1[2] = 3; |
| a20[0].s1[3] = 4; |
| a20[0].s2 = strdup("hello"); |
| a20[1].s1[0] = 5; |
| a20[1].s1[1] = 6; |
| a20[1].s1[2] = 7; |
| a20[1].s1[3] = 8; |
| a20[1].s2 = strdup("world"); |
| a20[i].s2 = strdup("hola"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a20[0].s1, input, 4); |
| clang_analyzer_eval(a20[0].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[0].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[0].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[0].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[0].s2 == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[1].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[1].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[1].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[1].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[1].s2 == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[i].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[i].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[i].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[i].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a20[i].s2 == 0); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'a20'}} |
| |
| return 0; |
| } |
| |
| // Test array's region and super region both having symbolic offsets. |
| int f21(int i) { |
| struct aa * a21 = malloc(sizeof(struct aa) * 2); |
| a21[0].s1[0] = 1; |
| a21[0].s1[1] = 2; |
| a21[0].s1[2] = 3; |
| a21[0].s1[3] = 4; |
| a21[0].s2 = 0; |
| a21[1].s1[0] = 5; |
| a21[1].s1[1] = 6; |
| a21[1].s1[2] = 7; |
| a21[1].s1[3] = 8; |
| a21[1].s2 = 0; |
| a21[i].s2 = strdup("hello"); |
| a21[i].s1[0] = 1; |
| a21[i].s1[1] = 2; |
| a21[i].s1[2] = 3; |
| a21[i].s1[3] = 4; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a21[i].s1, input, 4); |
| clang_analyzer_eval(a21[0].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[0].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[0].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[0].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[0].s2 == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[1].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[1].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[1].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[1].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[1].s2 == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[i].s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[i].s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[i].s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[i].s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a21[i].s2 == 0); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'a21'}} |
| |
| return 0; |
| } |
| |
| // Test regions aliasing other regions. |
| struct ll { |
| char s1[4]; |
| char * s2; |
| }; |
| |
| struct mm { |
| char s3[4]; |
| char * s4; |
| }; |
| |
| int f24() { |
| struct ll l24 = {{1, 2, 3, 4}, 0}; |
| struct mm * m24 = (struct mm *)&l24; |
| m24->s4 = strdup("hello"); |
| char input[] = {1, 2, 3, 4}; |
| memcpy(m24->s3, input, 4); |
| clang_analyzer_eval(m24->s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m24->s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m24->s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m24->s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l24.s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l24.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l24.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l24.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by field 's4'}} |
| return 0; |
| } |
| |
| // Test region with potential aliasing and symbolic offsets. |
| // Store assumes no aliasing. |
| int f25(int i, int j, struct ll * l, struct mm * m) { |
| m->s4 = strdup("hola"); // m->s4 not tracked |
| m->s3[0] = 1; |
| m->s3[1] = 2; |
| m->s3[2] = 3; |
| m->s3[3] = 4; |
| m->s3[j] = 5; // invalidates m->s3 |
| l->s2 = strdup("hello"); // l->s2 not tracked |
| l->s1[0] = 6; |
| l->s1[1] = 7; |
| l->s1[2] = 8; |
| l->s1[3] = 9; |
| l->s1[i] = 10; // invalidates l->s1 |
| char input[] = {1, 2, 3, 4}; |
| memcpy(m->s3, input, 4); // does not invalidate l->s1[i] |
| clang_analyzer_eval(m->s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m->s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m->s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m->s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m->s3[i] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m->s3[j] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l->s1[i] == 1); // expected-warning{{FALSE}} |
| clang_analyzer_eval(l->s1[j] == 1); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| // Test size with symbolic size argument. |
| int f26(int i) { |
| struct aa a26 = {{1, 2, 3, 4}, 0}; |
| a26.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a26.s1, input, i); // i assumed in bound |
| clang_analyzer_eval(a26.s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a26.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a26.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a26.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'a26.s2'}} |
| return 0; |
| } |
| |
| // Test sizeof as a size argument. |
| int f261() { |
| struct aa a261 = {{1, 2, 3, 4}, 0}; |
| a261.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a261.s1, input, sizeof(a261.s1)); |
| clang_analyzer_eval(a261.s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a261.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a261.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a261.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'a261.s2'}} |
| return 0; |
| } |
| |
| // Test negative size argument. |
| int f262() { |
| struct aa a262 = {{1, 2, 3, 4}, 0}; |
| a262.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(a262.s1, input, -1); |
| clang_analyzer_eval(a262.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'a262.s2'}} |
| clang_analyzer_eval(a262.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a262.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(a262.s1[3] == 1); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| // Test size argument being an unknown value. |
| struct xx { |
| char s1[4]; |
| char * s2; |
| }; |
| |
| int f263(int n, char * len) { |
| struct xx x263 = {0}; |
| x263.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(x263.s1, input, *(len + n)); |
| clang_analyzer_eval(x263.s1[0] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(x263.s1[1] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(x263.s1[2] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(x263.s1[3] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(x263.s2 == 0); // expected-warning{{UNKNOWN}} |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'x263.s2'}} |
| } |
| |
| |
| // Test casting regions with symbolic offseted sub regions. |
| int f27(int i) { |
| struct mm m27 = {{1, 2, 3, 4}, 0}; |
| m27.s4 = strdup("hello"); |
| m27.s3[i] = 5; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(((struct ll*)(&m27))->s1, input, 4); |
| clang_analyzer_eval(m27.s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m27.s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m27.s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m27.s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m27.s3[i] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'm27.s4'}} |
| return 0; |
| } |
| |
| int f28(int i, int j, int k, int l) { |
| struct mm m28[2]; |
| m28[i].s4 = strdup("hello"); |
| m28[j].s3[k] = 1; |
| struct ll * l28 = (struct ll*)(&m28[1]); |
| l28->s1[l] = 2; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(l28->s1, input, 4); |
| clang_analyzer_eval(m28[0].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[0].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[0].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[0].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[1].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[1].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[1].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[1].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[i].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[i].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[i].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[i].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m28[j].s3[k] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(l28->s1[l] == 2); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| int f29(int i, int j, int k, int l, int m) { |
| struct mm m29[2]; |
| m29[i].s4 = strdup("hello"); |
| m29[j].s3[k] = 1; |
| struct ll * l29 = (struct ll*)(&m29[l]); |
| l29->s1[m] = 2; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(l29->s1, input, 4); |
| clang_analyzer_eval(m29[0].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[0].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[0].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[0].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[1].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[1].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[1].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[1].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[i].s3[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[i].s3[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}} |
| clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}} |
| // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line, |
| // because l29 and m29 alias. |
| return 0; |
| } |
| |
| // Test unions' fields. |
| union uu { |
| char x; |
| char s1[4]; |
| }; |
| |
| int f30() { |
| union uu u30 = { .s1 = {1, 2, 3, 4}}; |
| char input[] = {1, 2, 3, 4}; |
| memcpy(u30.s1, input, 4); |
| clang_analyzer_eval(u30.s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(u30.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(u30.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(u30.s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(u30.x == 1); // expected-warning{{UNKNOWN}} |
| return 0; |
| } |
| |
| struct kk { |
| union uu u; |
| char * s2; |
| }; |
| |
| int f31() { |
| struct kk k31; |
| k31.s2 = strdup("hello"); |
| k31.u.x = 1; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(k31.u.s1, input, 4); |
| clang_analyzer_eval(k31.u.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'k31.s2'}} |
| clang_analyzer_eval(k31.u.s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(k31.u.s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(k31.u.s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(k31.u.x == 1); // expected-warning{{UNKNOWN}} |
| // FIXME: memory leak warning for k31.s2 should be emitted here. |
| return 0; |
| } |
| |
| union vv { |
| int x; |
| char * s2; |
| }; |
| |
| int f32() { |
| union vv v32; |
| v32.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(v32.s2, input, 4); |
| clang_analyzer_eval(v32.s2[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(v32.s2[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(v32.s2[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(v32.s2[3] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{Potential leak of memory pointed to by 'v32.s2'}} |
| return 0; |
| } |
| |
| struct nn { |
| int s1; |
| int i; |
| int j; |
| int k; |
| char * s2; |
| }; |
| |
| // Test bad types to dest buffer. |
| int f33() { |
| struct nn n33 = {1, 2, 3, 4, 0}; |
| n33.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(n33.s1, input, 4); // expected-warning{{incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'}} |
| clang_analyzer_eval(n33.i == 2); // expected-warning{{TRUE}} |
| clang_analyzer_eval(n33.j == 3); // expected-warning{{TRUE}} |
| clang_analyzer_eval(n33.k == 4); // expected-warning{{TRUE}} |
| clang_analyzer_eval(((char*)(n33.s1))[0] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
| clang_analyzer_eval(((char*)(n33.s1))[1] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
| clang_analyzer_eval(((char*)(n33.s1))[2] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
| clang_analyzer_eval(((char*)(n33.s1))[3] == 1); // expected-warning{{UNKNOWN}}\ |
| expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
| clang_analyzer_eval(n33.s2 == 0); //expected-warning{{UNKNOWN}} |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'n33.s2'}} |
| } |
| |
| // Test destination buffer being an unknown value. |
| struct ww { |
| int s1[4]; |
| char s2; |
| }; |
| |
| int f34(struct ww * w34, int n) { |
| w34->s2 = 3; |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(w34->s1 + n, input , 4); |
| clang_analyzer_eval(w34->s1[0] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(w34->s1[1] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(w34->s1[2] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(w34->s1[3] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(w34->s1[n] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(w34->s2 == 3); // expected-warning{{TRUE}} |
| return 0; |
| } |
| |
| // Test dest buffer as an element region with a symbolic index and size parameter as a symbolic value. |
| struct yy { |
| char s1[4]; |
| char * s2; |
| }; |
| |
| int f35(int i, int n) { |
| struct yy y35 = {{1, 2, 3, 4}, 0}; |
| y35.s2 = strdup("hello"); |
| char input[] = {'a', 'b', 'c', 'd'}; |
| memcpy(&(y35.s1[i]), input, n); |
| clang_analyzer_eval(y35.s1[0] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(y35.s1[1] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(y35.s1[2] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(y35.s1[3] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(y35.s1[i] == 0); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(y35.s2 == 0); // expected-warning{{UNKNOWN}} |
| return 0; // expected-warning{{Potential leak of memory pointed to by 'y35.s2'}} |
| } |
| |
| // Test regions with negative offsets. |
| struct zz { |
| char s1[4]; |
| int s2; |
| }; |
| |
| int f36(struct zz * z36) { |
| |
| char input[] = {'a', 'b', 'c', 'd'}; |
| z36->s1[0] = 0; |
| z36->s1[1] = 1; |
| z36->s1[2] = 2; |
| z36->s1[3] = 3; |
| z36->s2 = 10; |
| |
| z36 = z36 - 1; // Decrement by 8 bytes (struct zz is 8 bytes). |
| |
| z36->s1[0] = 4; |
| z36->s1[1] = 5; |
| z36->s1[2] = 6; |
| z36->s1[3] = 7; |
| z36->s2 = 11; |
| |
| memcpy(z36->s1, input, 4); |
| |
| clang_analyzer_eval(z36->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z36->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z36->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z36->s2 == 11); // expected-warning{{TRUE}} |
| |
| z36 = z36 + 1; // Increment back. |
| |
| clang_analyzer_eval(z36->s1[0] == 0); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z36->s1[2] == 2); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z36->s1[3] == 3); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z36->s2 == 10); // expected-warning{{TRUE}} |
| |
| return 0; |
| } |
| |
| int f37(struct zz * z37) { |
| |
| char input[] = {'a', 'b', 'c', 'd'}; |
| z37->s1[0] = 0; |
| z37->s1[1] = 1; |
| z37->s1[2] = 2; |
| z37->s1[3] = 3; |
| z37->s2 = 10; |
| |
| z37 = (struct zz *)((char*)(z37) - 4); // Decrement by 4 bytes (struct zz is 8 bytes). |
| |
| z37->s1[0] = 4; |
| z37->s1[1] = 5; |
| z37->s1[2] = 6; |
| z37->s1[3] = 7; |
| z37->s2 = 11; |
| |
| memcpy(z37->s1, input, 4); |
| |
| clang_analyzer_eval(z37->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s2 == 11); // expected-warning{{TRUE}} |
| |
| z37 = (struct zz *)((char*)(z37) + 4); // Increment back. |
| |
| clang_analyzer_eval(z37->s1[0] == 11); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z37->s2 == 10); // expected-warning{{TRUE}} |
| |
| return 0; |
| } |
| |
| int f38(struct zz * z38) { |
| |
| char input[] = {'a', 'b', 'c', 'd'}; |
| z38->s1[0] = 0; |
| z38->s1[1] = 1; |
| z38->s1[2] = 2; |
| z38->s1[3] = 3; |
| z38->s2 = 10; |
| |
| z38 = (struct zz *)((char*)(z38) - 2); // Decrement by 2 bytes (struct zz is 8 bytes). |
| |
| z38->s1[0] = 4; |
| z38->s1[1] = 5; |
| z38->s1[2] = 6; |
| z38->s1[3] = 7; |
| z38->s2 = 11; |
| |
| memcpy(z38->s1, input, 4); |
| |
| clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s2 == 11); // expected-warning{{TRUE}} |
| |
| z38 = (struct zz *)((char*)(z38) + 2); // Increment back. |
| |
| clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s1[2] == 11); // expected-warning{{TRUE}} |
| clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(z38->s2 == 10); // expected-warning{{UNKNOWN}} |
| |
| return 0; |
| } |
| |
| // Test negative offsets with a different structure layout. |
| struct z0 { |
| int s2; |
| char s1[4]; |
| }; |
| |
| int f39(struct z0 * d39) { |
| |
| char input[] = {'a', 'b', 'c', 'd'}; |
| d39->s1[0] = 0; |
| d39->s1[1] = 1; |
| d39->s1[2] = 2; |
| d39->s1[3] = 3; |
| d39->s2 = 10; |
| |
| d39 = (struct z0 *)((char*)(d39) - 2); // Decrement by 2 bytes (struct z0 is 8 bytes). |
| |
| d39->s1[0] = 4; |
| d39->s1[1] = 5; |
| d39->s1[2] = 6; |
| d39->s1[3] = 7; |
| d39->s2 = 11; |
| |
| memcpy(d39->s1, input, 4); |
| |
| clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s1[2] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s1[3] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s2 == 11); // expected-warning{{TRUE}} |
| |
| d39 = (struct z0 *)((char*)(d39) + 2); // Increment back. |
| |
| clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}} |
| clang_analyzer_eval(d39->s1[2] == 2); // expected-warning{{TRUE}} |
| clang_analyzer_eval(d39->s1[3] == 3); // expected-warning{{TRUE}} |
| // FIXME: d39->s2 should evaluate to at least UNKNOWN or FALSE, |
| // 'collectSubRegionBindings(...)' in RegionStore.cpp will need to |
| // handle a regions' upper boundary overflowing. |
| clang_analyzer_eval(d39->s2 == 10); // expected-warning{{TRUE}} |
| |
| return 0; |
| } |
| |