Skip to content

Commit 06dc52a

Browse files
committed
Release Assignment-2
1 parent af751f2 commit 06dc52a

File tree

4 files changed

+83
-84
lines changed

4 files changed

+83
-84
lines changed

Assignment-2/Assignment-2.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ bool SSE::handleRet(const RetCFGEdge* retEdge) {
6666

6767
/// TODO: Implement handling of branch statements inside a function
6868
/// Return true if the path is feasible, false otherwise.
69-
/// A given branch on the ICFG looks like the following:
69+
/// A given if/else branch on the ICFG looks like the following:
7070
/// ICFGNode1 (condition %cmp)
7171
/// 1 / \ 0
7272
/// ICFGNode2 ICFGNode3
73-
/// edge->getCondition() returns the branch condition variable (%cmp) of type SVFValue* (for if/else) or a numeric condition variable (for switch).
73+
/// edge->getCondition() returns the branch condition variable (%cmp) of type SVFValue* (for if/else) or a numeric condition variable (for switch).
7474
/// Given the condition variable, you could obtain the SVFVar ID via "svfir->getValueNode(edge->getCondition())""
7575
/// edge->getCondition() returns nullptr if this IntraCFGEdge is not a branch.
7676
/// edge->getSuccessorCondValue() returns the actual condition value (1/0 for if/else) when this branch/IntraCFGEdge is executed. For example, the successorCondValue is 1 on the edge from ICFGNode1 to ICFGNode2, and 0 on the edge from ICFGNode1 to ICFGNode3
@@ -159,10 +159,6 @@ bool SSE::handleNonBranch(const IntraCFGEdge* edge) {
159159
assert(false && "implement this part");
160160
}
161161
}
162-
else if (const BranchStmt *br = SVFUtil::dyn_cast<BranchStmt>(stmt))
163-
{
164-
DBOP(std::cout << "\t skip handled when traversal Conditional IntraCFGEdge \n");
165-
}
166162
else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt)) {
167163
expr res = getZ3Expr(select->getResID());
168164
expr tval = getZ3Expr(select->getTrueValue()->getId());
@@ -184,6 +180,9 @@ bool SSE::handleNonBranch(const IntraCFGEdge* edge) {
184180
}
185181
assert(opINodeFound && "predecessor ICFGNode of this PhiStmt not found?");
186182
}
183+
else {
184+
DBOP(std::cout << "\t skip handling BranchStmt/Call/Ret as they have been processed \n");
185+
}
187186
}
188187

189188
return true;
@@ -220,4 +219,4 @@ void SSE::analyse() {
220219
resetSolver();
221220
}
222221
}
223-
}
222+
}

Assignment-2/Assignment-2.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ namespace SVF {
7272
&& (fun->getName() == "assert" || fun->getName() == "svf_assert" || fun->getName() == "sink"));
7373
}
7474

75-
/// clear visited and callstack
75+
/// reset z3 solver
7676
virtual void resetSolver() {
77-
visited.clear();
77+
getSolver().reset();
7878
}
7979

8080
/// TODO: Implementing the collection the ICFG paths
@@ -114,19 +114,20 @@ namespace SVF {
114114
&& "last node is not an assert call?");
115115
DBOP(std::cout << "\n## Analyzing " << callnode->toString() << "\n");
116116
z3::expr arg0 = getZ3Expr(callnode->getActualParms().at(0)->getId());
117-
addToSolver(arg0 > 0);
118-
if (getSolver().check() == z3::unsat) {
117+
addToSolver(arg0 == getCtx().int_val(0));
118+
if (getSolver().check() != z3::unsat) {
119119
DBOP(printExprValues());
120120
std::stringstream ss;
121121
ss << "The assertion is unsatisfiable!! ("<< inode->toString() << ")" << "\n";
122+
ss << "Counterexample: " << getSolver().get_model() << "\n";
122123
SVFUtil::outs() << ss.str() << std::endl;
123124
assert(false);
124125
return false;
125126
}
126127
else {
127128
DBOP(printExprValues());
128129
std::stringstream ss;
129-
ss << "The assertion is successfully verified!! ("<< inode->toString() << ")" << "\n";
130+
ss << "The assertion is successfully verified!! ("<< inode->toString() << ")" << "\n";
130131
SVFUtil::outs() << ss.str() << std::endl;
131132
return true;
132133
}
@@ -136,6 +137,14 @@ namespace SVF {
136137
return paths;
137138
}
138139

140+
void pushCallingCtx(const SVFInstruction* c) {
141+
callingCtx.push_back(c);
142+
}
143+
144+
void popCallingCtx() {
145+
callingCtx.pop_back();
146+
}
147+
139148
inline z3::solver& getSolver() {
140149
return z3Mgr->getSolver();
141150
}
@@ -152,7 +161,7 @@ namespace SVF {
152161

153162
/// Return Z3 expression based on ValVar ID
154163
inline z3::expr getZ3Expr(NodeID idx) const {
155-
return z3Mgr->getZ3Expr(idx);
164+
return z3Mgr->getZ3Expr(idx, callingCtx);
156165
}
157166

158167
/// Return Z3 expression based on ObjVar ID
@@ -166,7 +175,7 @@ namespace SVF {
166175

167176
/// Dump values of all exprs
168177
inline void printExprValues() {
169-
z3Mgr->printExprValues();
178+
z3Mgr->printExprValues(callingCtx);
170179
}
171180

172181
static u32_t assert_checked;
@@ -181,6 +190,7 @@ namespace SVF {
181190
SVFIR* svfir;
182191
Set<ICFGEdgeStackPair> visited;
183192
CallStack callstack;
193+
CallStack callingCtx;
184194
std::vector<const ICFGEdge*> path;
185195

186196
std::set<const ICFGNode*> sources;

Assignment-2/Z3SSEMgr.cpp

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -39,59 +39,18 @@ using namespace z3;
3939
Z3SSEMgr::Z3SSEMgr(SVFIR* ir)
4040
: Z3Mgr(ir->getPAGNodeNum() * 10)
4141
, svfir(ir) {
42-
initMap();
4342
}
4443

45-
/*
46-
* (1) Create Z3 expressions for top-level variables and objects, and (2) create loc2val map
47-
*/
48-
void Z3SSEMgr::initMap() {
49-
for (SVFIR::iterator nIter = svfir->begin(); nIter != svfir->end(); ++nIter) {
50-
if (const ValVar* val = SVFUtil::dyn_cast<ValVar>(nIter->second))
51-
createExprForValVar(val);
52-
else if (const ObjVar* obj = SVFUtil::dyn_cast<ObjVar>(nIter->second))
53-
createExprForObjVar(obj);
54-
else
55-
assert(false && "SVFVar type not supported");
56-
}
57-
DBOP(printExprValues());
58-
}
59-
60-
/*
61-
* We initialize all ValVar to be an int expression.
62-
* ValVar of PointerTy/isFunctionTy is assigned with an ID to represent the address of an object
63-
* ValVar of IntegerTy is assigned with an integer value
64-
* ValVar of FloatingPointTy is assigned with an integer value casted from a float
65-
* ValVar of StructTy/ArrayTy is assigned with their elements of the above types in the form of integer values
66-
*/
67-
z3::expr Z3SSEMgr::createExprForValVar(const ValVar* valVar) {
68-
std::string str;
69-
raw_string_ostream rawstr(str);
70-
rawstr << "ValVar" << valVar->getId();
71-
expr e(ctx);
72-
if (const SVFType* type = valVar->getType()) {
73-
e = ctx.int_const(rawstr.str().c_str());
74-
}
75-
else {
76-
e = ctx.int_const(rawstr.str().c_str());
77-
assert(SVFUtil::isa<DummyValVar>(valVar) && "not a DummValVar if it has no type?");
78-
}
79-
80-
updateZ3Expr(valVar->getId(), e);
81-
return e;
82-
}
8344

8445
/*
85-
* Object must be either a constraint data or a location value (address-taken variable)
46+
* Object must be either a constaint data or a location value (address-taken variable)
8647
* Constant data includes ConstantInt, ConstantFP, ConstantPointerNull and ConstantAggregate
8748
* Locations includes pointers to globals, heaps, stacks
8849
*/
8950
z3::expr Z3SSEMgr::createExprForObjVar(const ObjVar* objVar) {
9051
std::string str;
9152
raw_string_ostream rawstr(str);
92-
rawstr << "ObjVar" << objVar->getId();
93-
94-
expr e = ctx.int_const(rawstr.str().c_str());
53+
expr e(ctx);
9554
if (objVar->hasValue()) {
9655
const MemObj* obj = objVar->getMemObj();
9756
/// constant data
@@ -122,30 +81,63 @@ z3::expr Z3SSEMgr::createExprForObjVar(const ObjVar* objVar) {
12281
&& "it should either be a blackhole or constant dummy if this obj has no value?");
12382
e = ctx.int_val(getVirtualMemAddress(objVar->getId()));
12483
}
125-
126-
updateZ3Expr(objVar->getId(), e);
12784
return e;
12885
}
12986

87+
std::string Z3SSEMgr::callingCtxToStr(const CallStack& callingCtx) {
88+
std::string str;
89+
std::stringstream rawstr(str);
90+
rawstr << "ctx:[ ";
91+
for (const auto &inst : callingCtx) {
92+
93+
rawstr << svfir->getICFG()->getICFGNode(inst)->getId() << " ";
94+
}
95+
rawstr << "] ";
96+
return rawstr.str();
97+
}
98+
99+
z3::expr Z3SSEMgr::getZ3Expr(SVF::u32_t idx, const CallStack& callingCtx) {
100+
u32_t varId = getInternalID(idx);
101+
assert(varId == idx && "SVFVar idx overflow > 0x7f000000?");
102+
std::string str;
103+
std::stringstream rawstr(str);
104+
const SVFVar *svfVar = svfir->getGNode(varId);
105+
if (const ObjVar* objVar = SVFUtil::dyn_cast<ObjVar>(svfVar)) {
106+
return createExprForObjVar(objVar);
107+
} else {
108+
109+
// Check if svfVar does not have a value or it has a constant value
110+
if (svfVar->hasValue() && !SVFUtil::isa<SVFConstant>(svfVar->getValue())) {
111+
// If there is a non-constant value, add callingCtx to z3 expr
112+
rawstr << callingCtxToStr(callingCtx);
113+
} else {
114+
// If there's no value or it's a constant, we do not add the callingCtx to z3 expr
115+
}
116+
rawstr << "ValVar" << varId;
117+
std::string name = rawstr.str();
118+
return ctx.int_const(name.c_str());
119+
}
120+
}
121+
130122
/// Return the address expr of a ObjVar
131-
z3::expr Z3SSEMgr::getMemObjAddress(u32_t idx) const {
123+
z3::expr Z3SSEMgr::getMemObjAddress(u32_t idx) {
132124
NodeID objIdx = getInternalID(idx);
133125
assert(SVFUtil::isa<ObjVar>(svfir->getGNode(objIdx)) && "Fail to get the MemObj!");
134-
return getZ3Expr(objIdx);
126+
return createExprForObjVar(SVFUtil::cast<ObjVar>(svfir->getGNode(objIdx)));
135127
}
136128

137129
z3::expr Z3SSEMgr::getGepObjAddress(z3::expr pointer, u32_t offset) {
138-
NodeID baseObj = getInternalID(z3Expr2NumValue(pointer));
139-
assert(SVFUtil::isa<ObjVar>(svfir->getGNode(baseObj)) && "Fail to get the base object address!");
140-
NodeID gepObj = svfir->getGepObjVar(baseObj, offset);
130+
NodeID obj = getInternalID(z3Expr2NumValue(pointer));
131+
assert(SVFUtil::isa<ObjVar>(svfir->getGNode(obj)) && "Fail to get the base object address!");
132+
NodeID gepObj = svfir->getGepObjVar(obj, offset);
141133
/// TODO: check whether this node has been created before or not to save creation time
142-
if (baseObj == gepObj)
143-
return getZ3Expr(baseObj);
134+
if (obj == gepObj)
135+
return createExprForObjVar(SVFUtil::cast<ObjVar>(svfir->getGNode(obj)));
144136
else
145137
return createExprForObjVar(SVFUtil::cast<GepObjVar>(svfir->getGNode(gepObj)));
146138
}
147139

148-
s32_t Z3SSEMgr::getGepOffset(const GepStmt* gep) {
140+
s32_t Z3SSEMgr::getGepOffset(const GepStmt* gep, const CallStack& callingCtx) {
149141
if (gep->getOffsetVarAndGepTypePairVec().empty())
150142
return gep->getConstantStructFldIdx();
151143

@@ -160,14 +152,14 @@ s32_t Z3SSEMgr::getGepOffset(const GepStmt* gep) {
160152
offset = op->getSExtValue();
161153
/// variable as the offset
162154
else
163-
offset = z3Expr2NumValue(getZ3Expr(svfir->getValueNode(value)));
155+
offset = z3Expr2NumValue(getZ3Expr(svfir->getValueNode(value), callingCtx));
164156

165157
if (type == nullptr) {
166158
totalOffset += offset;
167159
continue;
168160
}
169161

170-
/// Calculate the offset
162+
/// Caculate the offset
171163
if (const SVFPointerType* pty = SVFUtil::dyn_cast<SVFPointerType>(type))
172164
totalOffset += offset * gep->getAccessPath().getElementNum(gep->getAccessPath().gepSrcPointeeType());
173165
else
@@ -176,14 +168,14 @@ s32_t Z3SSEMgr::getGepOffset(const GepStmt* gep) {
176168
return totalOffset;
177169
}
178170

179-
void Z3SSEMgr::printExprValues() {
171+
void Z3SSEMgr::printExprValues(const CallStack& callingCtx) {
180172
std::cout.flags(std::ios::left);
181-
std::cout << "-----------SVFVar and Value-----------\n";
173+
std::cout << "\n-----------SVFVar and Value-----------\n";
182174
std::map<std::string, std::string> printValMap;
183175
std::map<NodeID, std::string> objKeyMap;
184176
std::map<NodeID, std::string> valKeyMap;
185177
for (SVFIR::iterator nIter = svfir->begin(); nIter != svfir->end(); ++nIter) {
186-
expr e = getEvalExpr(getZ3Expr(nIter->first));
178+
expr e = getEvalExpr(getZ3Expr(nIter->first, callingCtx));
187179
if (e.is_numeral()) {
188180
NodeID varID = nIter->second->getId();
189181
s32_t value = e.get_numeral_int64();
@@ -230,4 +222,4 @@ void Z3SSEMgr::printExprValues() {
230222
std::cout << std::setw(25) << printKey << printValMap[printKey];
231223
}
232224
std::cout << "-----------------------------------------\n";
233-
}
225+
}

Assignment-2/Z3SSEMgr.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define SOFTWARE_SECURITY_ANALYSIS_Z3SSEMGR_H
3030

3131
#include "Z3Mgr.h"
32+
#include "SVFIR/SVFIR.h"
3233

3334
namespace SVF {
3435

@@ -38,38 +39,35 @@ namespace SVF {
3839
class GepStmt;
3940

4041
class Z3SSEMgr : public Z3Mgr {
42+
typedef std::vector<const SVFInstruction*> CallStack;
4143
public:
4244
/// Constructor
4345
Z3SSEMgr(SVFIR* ir);
4446

45-
/// Initialize map (varID2ExprMap: ID->expr)from VARID to z3 expr ---
46-
/// Using elements from 0 to lastSlot Initialize map (loc2ValMap: ID->ID) from Location (pointer address) to
47-
/// Value --- Using the last slot V = L U C (V is SVFVar, L is Pointers + Nonconst Objects, C is Constants
48-
/// ) loc2ValMap : IDX(L) -> IDX(V) idx \in IDX(V) (IDX is a set of Indices of all SVFVars)
49-
void initMap();
5047

51-
/// Declare the expr type for each top-level pointers
52-
z3::expr createExprForValVar(const ValVar* val);
48+
std::string callingCtxToStr(const CallStack& callingCtx);
49+
50+
z3::expr getZ3Expr(u32_t idx, const CallStack& callingCtx);
5351

5452
/// Initialize the expr value for each objects (address-taken variables and constants)
5553
z3::expr createExprForObjVar(const ObjVar* obj);
5654

5755
/// Return the address expr of a ObjVar
58-
z3::expr getMemObjAddress(u32_t idx) const;
56+
z3::expr getMemObjAddress(u32_t idx);
5957

6058
/// Return the field address given a pointer points to a struct object and an offset
6159
z3::expr getGepObjAddress(z3::expr pointer, u32_t offset);
6260

6361
/// Return the offset expression of a GepStmt
64-
s32_t getGepOffset(const GepStmt* gep);
62+
s32_t getGepOffset(const GepStmt* gep, const CallStack& callingCtx);
6563

6664
/// Dump values of all exprs
67-
virtual void printExprValues();
65+
virtual void printExprValues(const CallStack& callingCtx);
6866

6967
private:
7068
SVFIR* svfir;
7169
};
7270

7371
} // namespace SVF
7472

75-
#endif // SOFTWARE_SECURITY_ANALYSIS_Z3MGR_H
73+
#endif // SOFTWARE_SECURITY_ANALYSIS_Z3MGR_H

0 commit comments

Comments
 (0)