Skip to content

Commit 0626df4

Browse files
committed
Fix analyzer regression reported in PR 4164:
- Update the old StoreManager::CastRegion to strip off 'ElementRegions' when casting to void* (Zhongxing: please validate) - Pass-by-reference argument invalidation logic in CFRefCount.cpp: - Strip ElementRegions when the ElementRegion is just a 'raw data' view on top of the underlying typed region. llvm-svn: 71094
1 parent 342053c commit 0626df4

File tree

3 files changed

+95
-13
lines changed

3 files changed

+95
-13
lines changed

clang/lib/Analysis/CFRefCount.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2606,7 +2606,29 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
26062606

26072607
const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
26082608

2609-
if (R) {
2609+
if (R) {
2610+
// Are we dealing with an ElementRegion? If the element type is
2611+
// a basic integer type (e.g., char, int) and the underying region
2612+
// is also typed then strip off the ElementRegion.
2613+
// FIXME: We really need to think about this for the general case
2614+
// as sometimes we are reasoning about arrays and other times
2615+
// about (char*), etc., is just a form of passing raw bytes.
2616+
// e.g., void *p = alloca(); foo((char*)p);
2617+
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
2618+
// Checking for 'integral type' is probably too promiscuous, but
2619+
// we'll leave it in for now until we have a systematic way of
2620+
// handling all of these cases. Eventually we need to come up
2621+
// with an interface to StoreManager so that this logic can be
2622+
// approriately delegated to the respective StoreManagers while
2623+
// still allowing us to do checker-specific logic (e.g.,
2624+
// invalidating reference counts), probably via callbacks.
2625+
if (ER->getElementType()->isIntegralType())
2626+
if (const TypedRegion *superReg =
2627+
dyn_cast<TypedRegion>(ER->getSuperRegion()))
2628+
R = superReg;
2629+
// FIXME: What about layers of ElementRegions?
2630+
}
2631+
26102632
// Is the invalidated variable something that we were tracking?
26112633
SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
26122634

clang/lib/Analysis/Store.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,37 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R,
4444
QualType Pointee = PTy->getPointeeType();
4545
if (Pointee->isVoidType()) {
4646

47-
// Casts to void* only removes TypedViewRegion. If there is no
48-
// TypedViewRegion, leave the region untouched. This happens when:
49-
//
50-
// void foo(void*);
51-
// ...
52-
// void bar() {
53-
// int x;
54-
// foo(&x);
55-
// }
56-
57-
if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R))
58-
R = TR->removeViews();
47+
do {
48+
if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
49+
// Casts to void* removes TypedViewRegion. This happens when:
50+
//
51+
// void foo(void*);
52+
// ...
53+
// void bar() {
54+
// int x;
55+
// foo(&x);
56+
// }
57+
//
58+
R = TR->removeViews();
59+
continue;
60+
}
61+
else if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
62+
// Casts to void* also removes ElementRegions. This happens when:
63+
//
64+
// void foo(void*);
65+
// ...
66+
// void bar() {
67+
// int x;
68+
// foo((char*)&x);
69+
// }
70+
//
71+
R = ER->getSuperRegion();
72+
continue;
73+
}
74+
else
75+
break;
76+
}
77+
while (0);
5978

6079
return CastResult(state, R);
6180
}

clang/test/Analysis/pr_4164.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=basic -verify %s &&
2+
// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=region -verify %s
3+
4+
// PR 4164: http://llvm.org/bugs/show_bug.cgi?id=4164
5+
//
6+
// Eventually this should be pulled into misc-ps.m. This is in a separate test
7+
// file for now to play around with the specific issues for BasicStoreManager
8+
// and StoreManager (i.e., we can make a copy of this file for either
9+
// StoreManager should one start to fail in the near future).
10+
//
11+
// The basic issue is that the VarRegion for 'size' is casted to (char*),
12+
// resulting in an ElementRegion. 'getsockopt' is an unknown function that
13+
// takes a void*, which means the ElementRegion should get stripped off.
14+
typedef unsigned int __uint32_t;
15+
typedef __uint32_t __darwin_socklen_t;
16+
typedef __darwin_socklen_t socklen_t;
17+
int getsockopt(int, int, int, void * restrict, socklen_t * restrict);
18+
19+
int test1() {
20+
int s = -1;
21+
int size;
22+
socklen_t size_len = sizeof(size);
23+
if (getsockopt(s, 0xffff, 0x1001, (char *)&size, &size_len) < 0)
24+
return -1;
25+
26+
return size; // no-warning
27+
}
28+
29+
// Similar case: instead of passing a 'void*', we pass 'char*'. In this
30+
// case we pass an ElementRegion to the invalidation logic. Since it is
31+
// an ElementRegion that just layers on top of another typed region and the
32+
// ElementRegion itself has elements whose type are integral (essentially raw
33+
// data) we strip off the ElementRegion when doing the invalidation.
34+
int takes_charptr(char* p);
35+
int test2() {
36+
int size;
37+
if (takes_charptr((char*)&size))
38+
return -1;
39+
return size; // no-warning
40+
}
41+

0 commit comments

Comments
 (0)