Static Value-Flow Analysis
Loading...
Searching...
No Matches
AbstractStateManager.cpp
Go to the documentation of this file.
1//===- AbstractStateManager.cpp -- AE state-access implementations ---//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22//
23// State-access bodies factored out of AbstractInterpretation.cpp /
24// SparseAbstractInterpretation.cpp. Class declarations stay in their
25// respective headers; this file just hosts the implementations of the
26// methods that used to live on the (now-folded) AbstractStateManager —
27// trace lookup, value get/has/update, GEP / load / store helpers, and
28// def/use queries — for dense and semi-sparse. Full-sparse stubs and
29// SVFG-backed overrides live in SparseAbstractInterpretation.cpp.
30//
31
34#include "SVFIR/SVFIR.h"
35#include "Util/Options.h"
36
37using namespace SVF;
38
39// =====================================================================
40// Dense (AbstractInterpretation) — direct trace lookup; sparse
41// subclasses override the virtuals below.
42// =====================================================================
43
45{
46 if (abstractTrace.count(node) == 0)
47 {
48 assert(false && "No preAbsTrace for this node");
49 abort();
50 }
51 return abstractTrace[node];
52}
53
58
61 dst.joinWith(src);
65{
66 return abstractTrace.count(node) != 0;
67}
68
81{
82 u32_t id = var->getId();
84 if (as.getVarToVal().count(id))
85 return as[id];
86 as[id] = IntervalValue::top();
87 return as[id];
88}
89
96
98{
99 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
100 return getAbsValue(objVar, node);
101 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
102 return getAbsValue(valVar, node);
103 assert(false && "Unknown SVFVar kind");
104 abort();
105}
106
112{
113 auto it = abstractTrace.find(node);
114 if (it == abstractTrace.end())
115 return false;
116 return it->second.getVarToVal().count(var->getId()) != 0;
117}
118
120{
121 auto it = abstractTrace.find(node);
122 if (it == abstractTrace.end())
123 return false;
124 return it->second.getLocToVal().count(var->getId()) != 0;
125}
126
128{
129 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
130 return hasAbsValue(objVar, node);
131 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
132 return hasAbsValue(valVar, node);
133 return false;
134}
135
138 abstractTrace[node][var->getId()] = val;
139}
140
145 as.store(addr, val);
146}
150 if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
151 updateAbsValue(objVar, val, node);
152 else if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
153 updateAbsValue(valVar, val, node);
154 else
155 assert(false && "Unknown SVFVar kind");
156}
157
159{
161 for (const ValVar* var : vars)
162 {
163 u32_t id = var->getId();
164 result[id] = as[id];
165 }
166}
167
169{
171 for (const ObjVar* var : vars)
172 {
174 result.store(addr, as.load(addr));
175 }
176}
177
179{
181 for (const SVFVar* var : vars)
182 {
183 if (const ValVar* valVar = SVFUtil::dyn_cast<ValVar>(var))
184 {
185 u32_t id = valVar->getId();
186 result[id] = as[id];
187 }
188 else if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(var))
189 {
191 result.store(addr, as.load(addr));
192 }
193 }
194}
195
197{
198 const ICFGNode* node = gep->getICFGNode();
199 if (gep->isConstantOffset())
200 return IntervalValue((s64_t)gep->accumulateConstantOffset());
201
202 IntervalValue res(0);
203 for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
204 {
205 const ValVar* var = gep->getOffsetVarAndGepTypePairVec()[i].first;
206 const SVFType* type = gep->getOffsetVarAndGepTypePairVec()[i].second;
207
209 if (const ConstIntValVar* constInt = SVFUtil::dyn_cast<ConstIntValVar>(var))
210 idxLb = idxUb = constInt->getSExtValue();
211 else
212 {
214 if (idxItv.isBottom())
215 idxLb = idxUb = 0;
216 else
217 {
219 idxUb = idxItv.ub().getIntNumeral();
220 }
221 }
222
223 if (SVFUtil::isa<SVFPointerType>(type))
224 {
225 u32_t elemNum = gep->getAccessPath().getElementNum(gep->getAccessPath().gepSrcPointeeType());
226 idxLb = (double)Options::MaxFieldLimit() / elemNum < idxLb ? Options::MaxFieldLimit() : idxLb * elemNum;
227 idxUb = (double)Options::MaxFieldLimit() / elemNum < idxUb ? Options::MaxFieldLimit() : idxUb * elemNum;
228 }
229 else
230 {
232 {
233 const std::vector<u32_t>& so = PAG::getPAG()->getTypeInfo(type)->getFlattenedElemIdxVec();
234 if (so.empty() || idxUb >= (APOffset)so.size() || idxLb < 0)
235 idxLb = idxUb = 0;
236 else
237 {
240 }
241 }
242 else
243 idxLb = idxUb = 0;
244 }
245 res = res + IntervalValue(idxLb, idxUb);
246 }
248 if (res.isBottom())
249 res = IntervalValue(0);
250 return res;
251}
252
254{
255 const ICFGNode* node = gep->getICFGNode();
256 if (gep->isConstantOffset())
257 return IntervalValue((s64_t)gep->accumulateConstantByteOffset());
258
259 IntervalValue res(0);
260 for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
261 {
262 const ValVar* idxOperandVar = gep->getOffsetVarAndGepTypePairVec()[i].first;
263 const SVFType* idxOperandType = gep->getOffsetVarAndGepTypePairVec()[i].second;
264
265 if (SVFUtil::isa<SVFArrayType>(idxOperandType) || SVFUtil::isa<SVFPointerType>(idxOperandType))
266 {
268 if (const SVFArrayType* arrOperandType = SVFUtil::dyn_cast<SVFArrayType>(idxOperandType))
269 elemByteSize = arrOperandType->getTypeOfElement()->getByteSize();
270 else if (SVFUtil::isa<SVFPointerType>(idxOperandType))
271 elemByteSize = gep->getAccessPath().gepSrcPointeeType()->getByteSize();
272 else
273 assert(false && "idxOperandType must be ArrType or PtrType");
274
275 if (const ConstIntValVar* op = SVFUtil::dyn_cast<ConstIntValVar>(idxOperandVar))
276 {
277 s64_t lb = (double)Options::MaxFieldLimit() / elemByteSize >= op->getSExtValue()
278 ? op->getSExtValue() * elemByteSize
280 res = res + IntervalValue(lb, lb);
281 }
282 else
283 {
285 if (idxVal.isBottom())
286 res = res + IntervalValue(0, 0);
287 else
288 {
289 s64_t ub = (idxVal.ub().getIntNumeral() < 0) ? 0
290 : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.ub().getIntNumeral()
291 ? elemByteSize * idxVal.ub().getIntNumeral()
293 s64_t lb = (idxVal.lb().getIntNumeral() < 0) ? 0
294 : (double)Options::MaxFieldLimit() / elemByteSize >= idxVal.lb().getIntNumeral()
295 ? elemByteSize * idxVal.lb().getIntNumeral()
297 res = res + IntervalValue(lb, ub);
298 }
299 }
300 }
301 else if (const SVFStructType* structOperandType = SVFUtil::dyn_cast<SVFStructType>(idxOperandType))
302 {
303 res = res + IntervalValue(gep->getAccessPath().getStructFieldOffset(idxOperandVar, structOperandType));
304 }
305 else
306 {
307 assert(false && "gep type pair only support arr/ptr/struct");
308 }
309 }
310 return res;
311}
312
314{
315 const ICFGNode* node = pointer->getICFGNode();
318 APOffset lb = offset.lb().getIntNumeral() < Options::MaxFieldLimit() ? offset.lb().getIntNumeral()
320 APOffset ub = offset.ub().getIntNumeral() < Options::MaxFieldLimit() ? offset.ub().getIntNumeral()
322 for (APOffset i = lb; i <= ub; i++)
323 {
324 const AbstractValue& addrs = getAbsValue(pointer, node);
325 for (const auto& addr : addrs.getAddrs())
326 {
327 s64_t baseObj = as.getIDFromAddr(addr);
328 assert(SVFUtil::isa<ObjVar>(svfir->getSVFVar(baseObj)) && "Fail to get the base object address!");
332 }
333 }
334 return gepAddrs;
335}
336
338{
339 const AbstractValue& ptrVal = getAbsValue(pointer, node);
341 AbstractValue res;
342 for (auto addr : ptrVal.getAddrs())
343 res.join_with(as.load(addr));
344 return res;
345}
346
347void AbstractInterpretation::storeValue(const ValVar* pointer, const AbstractValue& val, const ICFGNode* node)
348{
349 const AbstractValue& ptrVal = getAbsValue(pointer, node);
351 for (auto addr : ptrVal.getAddrs())
352 as.store(addr, val);
353}
354
356{
357 const AbstractValue& ptrVal = getAbsValue(var, node);
358 if (!ptrVal.isAddr())
359 return nullptr;
360 for (auto addr : ptrVal.getAddrs())
361 {
363 if (objId == 0)
364 continue;
365 return svfir->getBaseObject(objId)->getType();
366 }
367 return nullptr;
368}
369
371{
372 const ICFGNode* node = addr->getICFGNode();
373 if (const ObjVar* objvar = SVFUtil::dyn_cast<ObjVar>(addr->getRHSVar()))
374 {
376 {
377 return svfir->getBaseObject(objvar->getId())->getByteSizeOfObj();
378 }
379 else
380 {
381 const std::vector<SVFVar*>& sizes = addr->getArrSize();
382 u32_t elementSize = 1;
383 u64_t res = elementSize;
384 for (const SVFVar* value : sizes)
385 {
386 const AbstractValue& sizeVal = getAbsValue(value, node);
387 IntervalValue itv = sizeVal.getInterval();
388 if (itv.isBottom())
390 res = res * itv.ub().getIntNumeral() > Options::MaxFieldLimit()
391 ? Options::MaxFieldLimit() : res * itv.ub().getIntNumeral();
392 }
393 return (u32_t)res;
394 }
395 }
396 assert(false && "Addr rhs value is not ObjVar");
397 abort();
398}
399
400
401// =====================================================================
402// Semi-sparse state-access overrides (used by both SemiSparse and
403// FullSparse subclasses; the latter further restricts ValVar reads).
404// =====================================================================
405
407 const ICFGNode* node, const AbstractState& state)
408{
409 // Only replace ObjVar state. ValVars live at their def-sites and
410 // must not be overwritten when the predecessor's state is merged in.
411 abstractTrace[node].updateAddrStateOnly(state);
412}
413
415 AbstractState& dst, const AbstractState& src)
416{
417 // ValVars live at def-sites in semi-sparse mode; they don't flow
418 // through state merges. Snapshot dst's ValVar map, perform the full
419 // join, then restore the snapshot — leaving only ObjVars and freed
420 // addrs merged.
421 auto saved = dst.getVarToVal();
422 dst.joinWith(src);
423 dst.clearValVars();
424 for (const auto& [id, val] : saved)
425 dst[id] = val;
426}
427
429{
430 // const ValVars are all defined in global node
431 if (!var->getICFGNode())
432 {
433 return svfir->getICFG()->getGlobalICFGNode();
434 }
435 // for return value of callsite, use the ret-site as def-site
436 else if (SVFUtil::isa<CallICFGNode>(var->getICFGNode()) && SVFUtil::isa<RetValPN>(var))
437 {
438 return SVFUtil::dyn_cast<CallICFGNode>(var->getICFGNode())->getRetICFGNode();
439 }
440 // for other ValVars, use their def-site as the node to query abstract value.
441 else
442 {
443 return var->getICFGNode();
444 }
445}
446
452
458
460 const ValVar* var, const AbstractValue& val, const ICFGNode* node)
461{
462 // Write to the var's def-site so getAbsValue stays consistent.
463 const ICFGNode* defNode = var->getICFGNode();
464 abstractTrace[defNode ? defNode : node][var->getId()] = val;
465}
466
newitem type
Definition cJSON.cpp:2739
buffer offset
Definition cJSON.cpp:1113
AbstractState & getAbsState(const ICFGNode *node)
u32_t getAllocaInstByteSize(const AddrStmt *addr)
virtual bool hasAbsValue(const ValVar *var, const ICFGNode *node) const
Side-effect-free existence check.
IntervalValue getGepByteOffset(const GepStmt *gep)
AbstractValue loadValue(const ValVar *pointer, const ICFGNode *node)
AddressValue getGepObjAddrs(const ValVar *pointer, IntervalValue offset)
IntervalValue getGepElementIndex(const GepStmt *gep)
virtual void joinStates(AbstractState &dst, const AbstractState &src)
SVFIR * svfir
Data and helpers reachable from SparseAbstractInterpretation.
virtual const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node)
bool hasAbsState(const ICFGNode *node)
const SVFType * getPointeeElement(const ObjVar *var, const ICFGNode *node)
Map< const ICFGNode *, AbstractState > abstractTrace
per-node trace; owned here
virtual void updateAbsValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node)
void storeValue(const ValVar *pointer, const AbstractValue &val, const ICFGNode *node)
virtual void updateAbsState(const ICFGNode *node, const AbstractState &state)
const VarToAbsValMap & getVarToVal() const
get var2val map
u32_t getIDFromAddr(u32_t addr) const
Return the internal index if addr is an address otherwise return the value of idx.
void joinWith(const AbstractState &other)
domain join with other, important! other widen this.
static u32_t getVirtualMemAddress(u32_t idx)
The physical address starts with 0x7f...... + idx.
void join_with(const AbstractValue &other)
IntervalValue & getInterval()
AddressValue & getAddrs()
bool isConstantByteSize() const
Check if byte size is a const value.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
const SVFType * getType() const
Get obj type.
s64_t getIntNumeral() const
GlobalICFGNode * getGlobalICFGNode() const
Definition ICFG.h:244
u32_t getFlattenedElemIdx(const SVFType *T, u32_t origId)
Flattened element idx of an array or struct by considering stride.
Definition IRGraph.cpp:144
const StInfo * getTypeInfo(const SVFType *T) const
Get struct info.
Definition IRGraph.cpp:242
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
bool isBottom() const
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
static Option< bool > ModelArrays
Definition Options.h:185
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:35
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:496
ICFG * getICFG() const
Definition SVFIR.h:229
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:133
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:118
const GepObjVar * getGepObjVar(NodeID id) const
Definition SVFIR.h:167
u32_t getByteSize() const
Definition SVFType.h:289
const AbstractValue & getAbsValue(const ValVar *var, const ICFGNode *node) override
void joinStates(AbstractState &dst, const AbstractState &src) override
void updateAbsValue(const ValVar *var, const AbstractValue &val, const ICFGNode *node) override
bool hasAbsValue(const ValVar *var, const ICFGNode *node) const override
Side-effect-free existence check.
void updateAbsState(const ICFGNode *node, const AbstractState &state) override
const ICFGNode * getICFGNode(const ValVar *var) const
std::vector< u32_t > & getFlattenedElemIdxVec()
Definition SVFType.h:125
const ICFGNode * getICFGNode() const
for isBitcode
Definition BasicTypes.h:70
unsigned long long u64_t
Definition GeneralType.h:49
u32_t NodeID
Definition GeneralType.h:56
s64_t APOffset
Definition GeneralType.h:60
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:47
signed long long s64_t
Definition GeneralType.h:50