1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defined the types Store and StoreManager.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/Store.h"
#include "clang/Analysis/PathSensitive/GRState.h"
using namespace clang;
StoreManager::StoreManager(GRStateManager &stateMgr)
: ValMgr(stateMgr.getValueManager()),
StateMgr(stateMgr),
MRMgr(ValMgr.getRegionManager()) {}
StoreManager::CastResult
StoreManager::CastRegion(const GRState* state, const MemRegion* R,
QualType CastToTy) {
ASTContext& Ctx = StateMgr.getContext();
// We need to know the real type of CastToTy.
QualType ToTy = Ctx.getCanonicalType(CastToTy);
// Return the same region if the region types are compatible.
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
QualType Ta = Ctx.getCanonicalType(TR->getLocationType(Ctx));
if (Ta == ToTy)
return CastResult(state, R);
}
if (const PointerType* PTy = dyn_cast<PointerType>(ToTy.getTypePtr())) {
// Check if we are casting to 'void*'.
// FIXME: Handle arbitrary upcasts.
QualType Pointee = PTy->getPointeeType();
if (Pointee->isVoidType()) {
do {
if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
// Casts to void* removes TypedViewRegion. This happens when:
//
// void foo(void*);
// ...
// void bar() {
// int x;
// foo(&x);
// }
//
R = TR->removeViews();
continue;
}
else if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
// Casts to void* also removes ElementRegions. This happens when:
//
// void foo(void*);
// ...
// void bar() {
// int x;
// foo((char*)&x);
// }
//
R = ER->getSuperRegion();
continue;
}
else
break;
}
while (0);
return CastResult(state, R);
}
else if (Pointee->isIntegerType()) {
// FIXME: At some point, it stands to reason that this 'dyn_cast' should
// become a 'cast' and that 'R' will always be a TypedRegion.
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
// Check if we are casting to a region with an integer type. We now
// the types aren't the same, so we construct an ElementRegion.
SVal Idx = ValMgr.makeZeroArrayIndex();
// If the super region is an element region, strip it away.
// FIXME: Is this the right thing to do in all cases?
const MemRegion *Base = isa<ElementRegion>(TR) ? TR->getSuperRegion()
: TR;
ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base,
StateMgr.getContext());
return CastResult(state, ER);
}
}
}
// FIXME: Need to handle arbitrary downcasts.
// FIXME: Handle the case where a TypedViewRegion (layering a SymbolicRegion
// or an AllocaRegion is cast to another view, thus causing the memory
// to be re-used for a different purpose.
if (isa<SymbolicRegion>(R) || isa<AllocaRegion>(R)) {
const MemRegion* ViewR = MRMgr.getTypedViewRegion(CastToTy, R);
return CastResult(AddRegionView(state, ViewR, R), ViewR);
}
return CastResult(state, R);
}
const GRState *StoreManager::InvalidateRegion(const GRState *state,
const MemRegion *R,
const Expr *E, unsigned Count) {
ASTContext& Ctx = StateMgr.getContext();
if (!R->isBoundable())
return state;
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R)) {
// Invalidate the alloca region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
state = setDefaultValue(state, R, V);
return state;
}
const TypedRegion *TR = cast<TypedRegion>(R);
QualType T = TR->getValueType(Ctx);
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
return Bind(state, ValMgr.makeLoc(TR), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// FIXME: handle structs with default region value.
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
// No record definition. There is nothing we can do.
if (!RD)
return state;
// Iterate through the fields and construct new symbols.
for (RecordDecl::field_iterator FI=RD->field_begin(),
FE=RD->field_end(); FI!=FE; ++FI) {
// For now just handle scalar fields.
FieldDecl *FD = *FI;
QualType FT = FD->getType();
const FieldRegion* FR = MRMgr.getFieldRegion(FD, TR);
if (Loc::IsLocType(FT) ||
(FT->isIntegerType() && FT->isScalarType())) {
SVal V = ValMgr.getConjuredSymbolVal(E, FT, Count);
state = state->bindLoc(ValMgr.makeLoc(FR), V);
}
else if (FT->isStructureType()) {
// set the default value of the struct field to conjured
// symbol. Note that the type of the symbol is irrelavant.
// We cannot use the type of the struct otherwise ValMgr won't
// give us the conjured symbol.
SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
state = setDefaultValue(state, FR, V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
// Set the default value of the array to conjured symbol.
SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(),
Count);
state = setDefaultValue(state, TR, V);
} else {
// Just blast away other values.
state = Bind(state, ValMgr.makeLoc(TR), UnknownVal());
}
return state;
}
|