svf-tools 1.0.983 → 1.0.985
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +1 -1
- package/svf/include/CFL/CFLAlias.h +3 -3
- package/svf/include/Graphs/CHG.h +13 -31
- package/svf/include/Graphs/ICFG.h +2 -2
- package/svf/include/Graphs/ICFGEdge.h +4 -16
- package/svf/include/Graphs/ICFGNode.h +58 -0
- package/svf/include/Graphs/ThreadCallGraph.h +6 -6
- package/svf/include/MTA/MHP.h +3 -3
- package/svf/include/MTA/TCT.h +1 -1
- package/svf/include/SVFIR/SVFFileSystem.h +0 -2
- package/svf/include/SVFIR/SVFValue.h +0 -131
- package/svf/include/Util/SVFUtil.h +20 -37
- package/svf/include/Util/ThreadAPI.h +5 -26
- package/svf/include/WPA/Andersen.h +3 -3
- package/svf/include/WPA/Steensgaard.h +3 -3
- package/svf/include/WPA/WPAPass.h +3 -3
- package/svf/lib/AE/Svfexe/AEDetector.cpp +14 -18
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +66 -94
- package/svf/lib/CFL/CFLAlias.cpp +11 -12
- package/svf/lib/DDA/DDAClient.cpp +2 -2
- package/svf/lib/Graphs/CHG.cpp +33 -9
- package/svf/lib/Graphs/ICFG.cpp +13 -10
- package/svf/lib/MSSA/MemRegion.cpp +3 -3
- package/svf/lib/MTA/MHP.cpp +1 -1
- package/svf/lib/MemoryModel/PointerAnalysis.cpp +21 -23
- package/svf/lib/MemoryModel/PointerAnalysisImpl.cpp +2 -2
- package/svf/lib/SABER/SaberCondAllocator.cpp +1 -1
- package/svf/lib/SABER/SaberSVFGBuilder.cpp +1 -1
- package/svf/lib/SVFIR/SVFFileSystem.cpp +2 -20
- package/svf/lib/Util/SVFUtil.cpp +34 -18
- package/svf/lib/Util/ThreadAPI.cpp +32 -15
- package/svf/lib/WPA/Andersen.cpp +8 -9
- package/svf/lib/WPA/AndersenSCD.cpp +1 -2
- package/svf/lib/WPA/Steensgaard.cpp +8 -12
- package/svf/lib/WPA/TypeAnalysis.cpp +2 -3
- package/svf/lib/WPA/WPAPass.cpp +6 -13
- package/svf-llvm/include/SVF-LLVM/DCHG.h +7 -7
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +0 -8
- package/svf-llvm/lib/CHGBuilder.cpp +4 -4
- package/svf-llvm/lib/DCHG.cpp +8 -7
- package/svf-llvm/lib/ICFGBuilder.cpp +2 -2
- package/svf-llvm/lib/LLVMModule.cpp +0 -2
- package/svf-llvm/lib/LLVMUtil.cpp +0 -58
- package/svf-llvm/lib/SVFIRExtAPI.cpp +2 -2
|
@@ -171,7 +171,7 @@ class Andersen: public AndersenBase
|
|
|
171
171
|
|
|
172
172
|
public:
|
|
173
173
|
typedef SCCDetection<ConstraintGraph*> CGSCC;
|
|
174
|
-
typedef OrderedMap<
|
|
174
|
+
typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
|
|
175
175
|
|
|
176
176
|
/// Constructor
|
|
177
177
|
Andersen(SVFIR* _pag, PTATY type = Andersen_WPA, bool alias_check = true)
|
|
@@ -243,7 +243,7 @@ public:
|
|
|
243
243
|
protected:
|
|
244
244
|
|
|
245
245
|
CallSite2DummyValPN callsite2DummyValPN; ///< Map an instruction to a dummy obj which created at an indirect callsite, which invokes a heap allocator
|
|
246
|
-
void heapAllocatorViaIndCall(
|
|
246
|
+
void heapAllocatorViaIndCall(const CallICFGNode* cs,NodePairSet &cpySrcNodes);
|
|
247
247
|
|
|
248
248
|
/// Handle diff points-to set.
|
|
249
249
|
virtual inline void computeDiffPts(NodeID id)
|
|
@@ -315,7 +315,7 @@ protected:
|
|
|
315
315
|
virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
|
|
316
316
|
|
|
317
317
|
/// Connect formal and actual parameters for indirect callsites
|
|
318
|
-
void connectCaller2CalleeParams(
|
|
318
|
+
void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet& cpySrcNodes);
|
|
319
319
|
|
|
320
320
|
/// Merge sub node to its rep
|
|
321
321
|
virtual void mergeNodeToRep(NodeID nodeId,NodeID newRepId);
|
|
@@ -23,7 +23,7 @@ class Steensgaard : public AndersenBase
|
|
|
23
23
|
public:
|
|
24
24
|
typedef Map<NodeID, NodeID> NodeToEquivClassMap;
|
|
25
25
|
typedef Map<NodeID, Set<NodeID>> NodeToSubsMap;
|
|
26
|
-
typedef OrderedMap<
|
|
26
|
+
typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
|
|
27
27
|
|
|
28
28
|
/// Constructor
|
|
29
29
|
Steensgaard(SVFIR* _pag) : AndersenBase(_pag, Steensgaard_WPA, true) {}
|
|
@@ -121,13 +121,13 @@ protected:
|
|
|
121
121
|
callsite2DummyValPN; ///< Map an instruction to a dummy obj which
|
|
122
122
|
///< created at an indirect callsite, which invokes
|
|
123
123
|
///< a heap allocator
|
|
124
|
-
void heapAllocatorViaIndCall(
|
|
124
|
+
void heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes);
|
|
125
125
|
|
|
126
126
|
/// Update call graph for the input indirect callsites
|
|
127
127
|
virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
|
|
128
128
|
|
|
129
129
|
/// Connect formal and actual parameters for indirect callsites
|
|
130
|
-
void connectCaller2CalleeParams(
|
|
130
|
+
void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
|
|
131
131
|
NodePairSet& cpySrcNodes);
|
|
132
132
|
|
|
133
133
|
private:
|
|
@@ -86,7 +86,7 @@ public:
|
|
|
86
86
|
virtual void PrintAliasPairs(PointerAnalysis* pta);
|
|
87
87
|
|
|
88
88
|
/// Interface of mod-ref analysis to determine whether a CallSite instruction can mod or ref any memory location
|
|
89
|
-
virtual ModRefInfo getModRefInfo(const
|
|
89
|
+
virtual ModRefInfo getModRefInfo(const CallICFGNode* callInst);
|
|
90
90
|
|
|
91
91
|
/// Interface of mod-ref analysis to determine whether a CallSite instruction can mod or ref a specific memory location, given Location infos
|
|
92
92
|
// virtual inline ModRefInfo getModRefInfo(const CallSite callInst, const MemoryLocation& Loc)
|
|
@@ -95,10 +95,10 @@ public:
|
|
|
95
95
|
// }
|
|
96
96
|
|
|
97
97
|
/// Interface of mod-ref analysis to determine whether a CallSite instruction can mod or ref a specific memory location, given Value infos
|
|
98
|
-
virtual ModRefInfo getModRefInfo(const
|
|
98
|
+
virtual ModRefInfo getModRefInfo(const CallICFGNode* callInst, const SVFValue* V);
|
|
99
99
|
|
|
100
100
|
/// Interface of mod-ref analysis between two CallSite instructions
|
|
101
|
-
virtual ModRefInfo getModRefInfo(const
|
|
101
|
+
virtual ModRefInfo getModRefInfo(const CallICFGNode* callInst1, const CallICFGNode* callInst2);
|
|
102
102
|
|
|
103
103
|
/// Run pointer analysis on SVFModule
|
|
104
104
|
virtual void runOnModule(SVFIR* svfModule);
|
|
@@ -148,7 +148,6 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
148
148
|
SVFIR* svfir = PAG::getPAG();
|
|
149
149
|
const SVFFunction *fun = SVFUtil::getCallee(call->getCallSite());
|
|
150
150
|
assert(fun && "SVFFunction* is nullptr");
|
|
151
|
-
CallSite cs = SVFUtil::getSVFCallSite(call);
|
|
152
151
|
|
|
153
152
|
AbstractInterpretation::ExtAPIType extType = AbstractInterpretation::UNCLASSIFIED;
|
|
154
153
|
|
|
@@ -177,10 +176,10 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
177
176
|
extAPIBufOverflowCheckRules.at(fun->getName());
|
|
178
177
|
for (auto arg : args)
|
|
179
178
|
{
|
|
180
|
-
IntervalValue offset = as[svfir->getValueNode(
|
|
181
|
-
if (!canSafelyAccessMemory(as,
|
|
179
|
+
IntervalValue offset = as[svfir->getValueNode(call->getArgument(arg.second))].getInterval() - IntervalValue(1);
|
|
180
|
+
if (!canSafelyAccessMemory(as, call->getArgument(arg.first), offset))
|
|
182
181
|
{
|
|
183
|
-
AEException bug(call->
|
|
182
|
+
AEException bug(call->toString());
|
|
184
183
|
addBugToReporter(bug, call);
|
|
185
184
|
}
|
|
186
185
|
}
|
|
@@ -196,10 +195,10 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
196
195
|
extAPIBufOverflowCheckRules.at(fun->getName());
|
|
197
196
|
for (auto arg : args)
|
|
198
197
|
{
|
|
199
|
-
IntervalValue offset = as[svfir->getValueNode(
|
|
200
|
-
if (!canSafelyAccessMemory(as,
|
|
198
|
+
IntervalValue offset = as[svfir->getValueNode(call->getArgument(arg.second))].getInterval() - IntervalValue(1);
|
|
199
|
+
if (!canSafelyAccessMemory(as, call->getArgument(arg.first), offset))
|
|
201
200
|
{
|
|
202
|
-
AEException bug(call->
|
|
201
|
+
AEException bug(call->toString());
|
|
203
202
|
addBugToReporter(bug, call);
|
|
204
203
|
}
|
|
205
204
|
}
|
|
@@ -208,7 +207,7 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
208
207
|
{
|
|
209
208
|
if (!detectStrcpy(as, call))
|
|
210
209
|
{
|
|
211
|
-
AEException bug(call->
|
|
210
|
+
AEException bug(call->toString());
|
|
212
211
|
addBugToReporter(bug, call);
|
|
213
212
|
}
|
|
214
213
|
}
|
|
@@ -216,7 +215,7 @@ void BufOverflowDetector::detectExtAPI(AbstractState& as,
|
|
|
216
215
|
{
|
|
217
216
|
if (!detectStrcat(as, call))
|
|
218
217
|
{
|
|
219
|
-
AEException bug(call->
|
|
218
|
+
AEException bug(call->toString());
|
|
220
219
|
addBugToReporter(bug, call);
|
|
221
220
|
}
|
|
222
221
|
}
|
|
@@ -322,9 +321,8 @@ void BufOverflowDetector::updateGepObjOffsetFromBase(SVF::AddressValue gepAddrs,
|
|
|
322
321
|
*/
|
|
323
322
|
bool BufOverflowDetector::detectStrcpy(AbstractState& as, const CallICFGNode *call)
|
|
324
323
|
{
|
|
325
|
-
|
|
326
|
-
const SVFValue*
|
|
327
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
324
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
325
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
328
326
|
IntervalValue strLen = AbstractInterpretation::getAEInstance().getStrlen(as, arg1Val);
|
|
329
327
|
return canSafelyAccessMemory(as, arg0Val, strLen);
|
|
330
328
|
}
|
|
@@ -349,9 +347,8 @@ bool BufOverflowDetector::detectStrcat(AbstractState& as, const CallICFGNode *ca
|
|
|
349
347
|
|
|
350
348
|
if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
|
|
351
349
|
{
|
|
352
|
-
|
|
353
|
-
const SVFValue*
|
|
354
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
350
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
351
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
355
352
|
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getStrlen(as, arg0Val);
|
|
356
353
|
IntervalValue strLen1 = AbstractInterpretation::getAEInstance().getStrlen(as, arg1Val);
|
|
357
354
|
IntervalValue totalLen = strLen0 + strLen1;
|
|
@@ -359,9 +356,8 @@ bool BufOverflowDetector::detectStrcat(AbstractState& as, const CallICFGNode *ca
|
|
|
359
356
|
}
|
|
360
357
|
else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
|
|
361
358
|
{
|
|
362
|
-
|
|
363
|
-
const SVFValue*
|
|
364
|
-
const SVFValue* arg2Val = cs.getArgument(2);
|
|
359
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
360
|
+
const SVFValue* arg2Val = call->getArgument(2);
|
|
365
361
|
IntervalValue arg2Num = as[svfir->getValueNode(arg2Val)].getInterval();
|
|
366
362
|
IntervalValue strLen0 = AbstractInterpretation::getAEInstance().getStrlen(as, arg0Val);
|
|
367
363
|
IntervalValue totalLen = strLen0 + arg2Num;
|
|
@@ -906,7 +906,7 @@ void AEStat::finializeStat()
|
|
|
906
906
|
}
|
|
907
907
|
if (const CallICFGNode *callNode = dyn_cast<CallICFGNode>(it.second))
|
|
908
908
|
{
|
|
909
|
-
if (!isExtCall(callNode
|
|
909
|
+
if (!isExtCall(callNode))
|
|
910
910
|
{
|
|
911
911
|
callSiteNum++;
|
|
912
912
|
}
|
|
@@ -963,16 +963,14 @@ void AEStat::performStat()
|
|
|
963
963
|
void AbstractInterpretation::initExtFunMap()
|
|
964
964
|
{
|
|
965
965
|
#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
|
|
966
|
-
auto sse_##FUNC_NAME = [this](const
|
|
966
|
+
auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
|
|
967
967
|
/* run real ext function */ \
|
|
968
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>( \
|
|
969
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction())); \
|
|
970
968
|
AbstractState& as = getAbsStateFromTrace(callNode); \
|
|
971
|
-
u32_t rhs_id = svfir->getValueNode(
|
|
969
|
+
u32_t rhs_id = svfir->getValueNode(callNode->getArgument(0)); \
|
|
972
970
|
if (!as.inVarToValTable(rhs_id)) return; \
|
|
973
971
|
u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
|
|
974
972
|
s32_t res = FUNC_NAME(rhs); \
|
|
975
|
-
u32_t lhsId = svfir->getValueNode(
|
|
973
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite()); \
|
|
976
974
|
as[lhsId] = IntervalValue(res); \
|
|
977
975
|
return; \
|
|
978
976
|
}; \
|
|
@@ -997,12 +995,10 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
997
995
|
SSE_FUNC_PROCESS(cosh, cosh);
|
|
998
996
|
SSE_FUNC_PROCESS(tanh, tanh);
|
|
999
997
|
|
|
1000
|
-
auto sse_svf_assert = [this](const
|
|
998
|
+
auto sse_svf_assert = [this](const CallICFGNode* callNode)
|
|
1001
999
|
{
|
|
1002
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1003
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1004
1000
|
checkpoints.erase(callNode);
|
|
1005
|
-
u32_t arg0 = svfir->getValueNode(
|
|
1001
|
+
u32_t arg0 = svfir->getValueNode(callNode->getArgument(0));
|
|
1006
1002
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1007
1003
|
as[arg0].getInterval().meet_with(IntervalValue(1, 1));
|
|
1008
1004
|
if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
|
|
@@ -1011,38 +1007,34 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1011
1007
|
}
|
|
1012
1008
|
else
|
|
1013
1009
|
{
|
|
1014
|
-
SVFUtil::errs() <<"svf_assert Fail. " <<
|
|
1010
|
+
SVFUtil::errs() <<"svf_assert Fail. " << callNode->toString() << "\n";
|
|
1015
1011
|
assert(false);
|
|
1016
1012
|
}
|
|
1017
1013
|
return;
|
|
1018
1014
|
};
|
|
1019
1015
|
func_map["svf_assert"] = sse_svf_assert;
|
|
1020
1016
|
|
|
1021
|
-
auto svf_print = [&](const
|
|
1017
|
+
auto svf_print = [&](const CallICFGNode* callNode)
|
|
1022
1018
|
{
|
|
1023
|
-
if (
|
|
1024
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1025
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1019
|
+
if (callNode->arg_size() < 2) return;
|
|
1026
1020
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1027
|
-
u32_t num_id = svfir->getValueNode(
|
|
1028
|
-
std::string text = strRead(as,
|
|
1021
|
+
u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
|
|
1022
|
+
std::string text = strRead(as, callNode->getArgument(1));
|
|
1029
1023
|
assert(as.inVarToValTable(num_id) && "print() should pass integer");
|
|
1030
1024
|
IntervalValue itv = as[num_id].getInterval();
|
|
1031
|
-
std::cout << "Text: " << text <<", Value: " <<
|
|
1025
|
+
std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString() << ", PrintVal: " << itv.toString() << std::endl;
|
|
1032
1026
|
return;
|
|
1033
1027
|
};
|
|
1034
1028
|
func_map["svf_print"] = svf_print;
|
|
1035
1029
|
|
|
1036
1030
|
|
|
1037
|
-
auto sse_scanf = [&](const
|
|
1031
|
+
auto sse_scanf = [&](const CallICFGNode* callNode)
|
|
1038
1032
|
{
|
|
1039
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1040
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1041
1033
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1042
1034
|
//scanf("%d", &data);
|
|
1043
|
-
if (
|
|
1035
|
+
if (callNode->arg_size() < 2) return;
|
|
1044
1036
|
|
|
1045
|
-
u32_t dst_id = svfir->getValueNode(
|
|
1037
|
+
u32_t dst_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1046
1038
|
if (!as.inVarToAddrsTable(dst_id))
|
|
1047
1039
|
{
|
|
1048
1040
|
return;
|
|
@@ -1058,14 +1050,12 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1058
1050
|
}
|
|
1059
1051
|
}
|
|
1060
1052
|
};
|
|
1061
|
-
auto sse_fscanf = [&](const
|
|
1053
|
+
auto sse_fscanf = [&](const CallICFGNode* callNode)
|
|
1062
1054
|
{
|
|
1063
1055
|
//fscanf(stdin, "%d", &data);
|
|
1064
|
-
if (
|
|
1065
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1066
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1056
|
+
if (callNode->arg_size() < 3) return;
|
|
1067
1057
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1068
|
-
u32_t dst_id = svfir->getValueNode(
|
|
1058
|
+
u32_t dst_id = svfir->getValueNode(callNode->getArgument(2));
|
|
1069
1059
|
if (!as.inVarToAddrsTable(dst_id))
|
|
1070
1060
|
{
|
|
1071
1061
|
}
|
|
@@ -1090,42 +1080,38 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1090
1080
|
func_map["__isoc99_sscanf"] = sse_scanf;
|
|
1091
1081
|
func_map["vscanf"] = sse_scanf;
|
|
1092
1082
|
|
|
1093
|
-
auto sse_fread = [&](const
|
|
1083
|
+
auto sse_fread = [&](const CallICFGNode *callNode)
|
|
1094
1084
|
{
|
|
1095
|
-
if (
|
|
1096
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1097
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1085
|
+
if (callNode->arg_size() < 3) return;
|
|
1098
1086
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1099
|
-
u32_t block_count_id = svfir->getValueNode(
|
|
1100
|
-
u32_t block_size_id = svfir->getValueNode(
|
|
1087
|
+
u32_t block_count_id = svfir->getValueNode(callNode->getArgument(2));
|
|
1088
|
+
u32_t block_size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1101
1089
|
IntervalValue block_count = as[block_count_id].getInterval();
|
|
1102
1090
|
IntervalValue block_size = as[block_size_id].getInterval();
|
|
1103
1091
|
IntervalValue block_byte = block_count * block_size;
|
|
1104
1092
|
};
|
|
1105
1093
|
func_map["fread"] = sse_fread;
|
|
1106
1094
|
|
|
1107
|
-
auto sse_sprintf = [&](const
|
|
1095
|
+
auto sse_sprintf = [&](const CallICFGNode *callNode)
|
|
1108
1096
|
{
|
|
1109
1097
|
// printf is difficult to predict since it has no byte size arguments
|
|
1110
1098
|
};
|
|
1111
1099
|
|
|
1112
|
-
auto sse_snprintf = [&](const
|
|
1100
|
+
auto sse_snprintf = [&](const CallICFGNode *callNode)
|
|
1113
1101
|
{
|
|
1114
|
-
if (
|
|
1115
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1116
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1102
|
+
if (callNode->arg_size() < 2) return;
|
|
1117
1103
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1118
|
-
u32_t size_id = svfir->getValueNode(
|
|
1119
|
-
u32_t dst_id = svfir->getValueNode(
|
|
1104
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1105
|
+
u32_t dst_id = svfir->getValueNode(callNode->getArgument(0));
|
|
1120
1106
|
// get elem size of arg2
|
|
1121
1107
|
u32_t elemSize = 1;
|
|
1122
|
-
if (
|
|
1108
|
+
if (callNode->getArgument(2)->getType()->isArrayTy())
|
|
1123
1109
|
{
|
|
1124
|
-
elemSize = SVFUtil::dyn_cast<SVFArrayType>(
|
|
1110
|
+
elemSize = SVFUtil::dyn_cast<SVFArrayType>(callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
|
|
1125
1111
|
}
|
|
1126
|
-
else if (
|
|
1112
|
+
else if (callNode->getArgument(2)->getType()->isPointerTy())
|
|
1127
1113
|
{
|
|
1128
|
-
elemSize = as.getPointeeElement(svfir->getValueNode(
|
|
1114
|
+
elemSize = as.getPointeeElement(svfir->getValueNode(callNode->getArgument(2)))->getByteSize();
|
|
1129
1115
|
}
|
|
1130
1116
|
else
|
|
1131
1117
|
{
|
|
@@ -1149,15 +1135,13 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1149
1135
|
func_map["_snwprintf"] = sse_snprintf;
|
|
1150
1136
|
|
|
1151
1137
|
|
|
1152
|
-
auto sse_itoa = [&](const
|
|
1138
|
+
auto sse_itoa = [&](const CallICFGNode* callNode)
|
|
1153
1139
|
{
|
|
1154
1140
|
// itoa(num, ch, 10);
|
|
1155
1141
|
// num: int, ch: char*, 10 is decimal
|
|
1156
|
-
if (
|
|
1157
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1158
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1142
|
+
if (callNode->arg_size() < 3) return;
|
|
1159
1143
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1160
|
-
u32_t num_id = svfir->getValueNode(
|
|
1144
|
+
u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
|
|
1161
1145
|
|
|
1162
1146
|
u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
|
|
1163
1147
|
std::string snum = std::to_string(num);
|
|
@@ -1165,16 +1149,14 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1165
1149
|
func_map["itoa"] = sse_itoa;
|
|
1166
1150
|
|
|
1167
1151
|
|
|
1168
|
-
auto sse_strlen = [&](const
|
|
1152
|
+
auto sse_strlen = [&](const CallICFGNode *callNode)
|
|
1169
1153
|
{
|
|
1170
1154
|
// check the arg size
|
|
1171
|
-
if (
|
|
1172
|
-
const SVFValue* strValue =
|
|
1173
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1174
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1155
|
+
if (callNode->arg_size() < 1) return;
|
|
1156
|
+
const SVFValue* strValue = callNode->getArgument(0);
|
|
1175
1157
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1176
1158
|
NodeID value_id = svfir->getValueNode(strValue);
|
|
1177
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1159
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
|
|
1178
1160
|
u32_t dst_size = 0;
|
|
1179
1161
|
for (const auto& addr : as[value_id].getAddrs())
|
|
1180
1162
|
{
|
|
@@ -1227,29 +1209,25 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1227
1209
|
func_map["strlen"] = sse_strlen;
|
|
1228
1210
|
func_map["wcslen"] = sse_strlen;
|
|
1229
1211
|
|
|
1230
|
-
auto sse_recv = [&](const
|
|
1212
|
+
auto sse_recv = [&](const CallICFGNode *callNode)
|
|
1231
1213
|
{
|
|
1232
1214
|
// recv(sockfd, buf, len, flags);
|
|
1233
|
-
if (
|
|
1234
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1235
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1215
|
+
if (callNode->arg_size() < 4) return;
|
|
1236
1216
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1237
|
-
u32_t len_id = svfir->getValueNode(
|
|
1217
|
+
u32_t len_id = svfir->getValueNode(callNode->getArgument(2));
|
|
1238
1218
|
IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
|
|
1239
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1219
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
|
|
1240
1220
|
as[lhsId] = len;
|
|
1241
1221
|
};
|
|
1242
1222
|
func_map["recv"] = sse_recv;
|
|
1243
1223
|
func_map["__recv"] = sse_recv;
|
|
1244
|
-
auto safe_bufaccess = [&](const
|
|
1224
|
+
auto safe_bufaccess = [&](const CallICFGNode *callNode)
|
|
1245
1225
|
{
|
|
1246
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1247
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1248
1226
|
checkpoints.erase(callNode);
|
|
1249
1227
|
//void SAFE_BUFACCESS(void* data, int size);
|
|
1250
|
-
if (
|
|
1228
|
+
if (callNode->arg_size() < 2) return;
|
|
1251
1229
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1252
|
-
u32_t size_id = svfir->getValueNode(
|
|
1230
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1253
1231
|
IntervalValue val = as[size_id].getInterval();
|
|
1254
1232
|
if (val.isBottom())
|
|
1255
1233
|
{
|
|
@@ -1262,7 +1240,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1262
1240
|
if (SVFUtil::isa<BufOverflowDetector>(detector))
|
|
1263
1241
|
{
|
|
1264
1242
|
BufOverflowDetector* bufDetector = SVFUtil::cast<BufOverflowDetector>(detector.get());
|
|
1265
|
-
bool isSafe = bufDetector->canSafelyAccessMemory(as,
|
|
1243
|
+
bool isSafe = bufDetector->canSafelyAccessMemory(as, callNode->getArgument(0), val);
|
|
1266
1244
|
if (isSafe)
|
|
1267
1245
|
{
|
|
1268
1246
|
std::cout << "safe buffer access success: " << callNode->toString() << std::endl;
|
|
@@ -1271,7 +1249,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1271
1249
|
else
|
|
1272
1250
|
{
|
|
1273
1251
|
std::string err_msg = "this SAFE_BUFACCESS should be a safe access but detected buffer overflow. Pos: ";
|
|
1274
|
-
err_msg +=
|
|
1252
|
+
err_msg += callNode->getSourceLoc();
|
|
1275
1253
|
std::cerr << err_msg << std::endl;
|
|
1276
1254
|
assert(false);
|
|
1277
1255
|
}
|
|
@@ -1280,15 +1258,13 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1280
1258
|
};
|
|
1281
1259
|
func_map["SAFE_BUFACCESS"] = safe_bufaccess;
|
|
1282
1260
|
|
|
1283
|
-
auto unsafe_bufaccess = [&](const
|
|
1261
|
+
auto unsafe_bufaccess = [&](const CallICFGNode *callNode)
|
|
1284
1262
|
{
|
|
1285
|
-
const CallICFGNode* callNode = SVFUtil::dyn_cast<CallICFGNode>(
|
|
1286
|
-
svfir->getICFG()->getICFGNode(cs.getInstruction()));
|
|
1287
1263
|
checkpoints.erase(callNode);
|
|
1288
1264
|
//void UNSAFE_BUFACCESS(void* data, int size);
|
|
1289
|
-
if (
|
|
1265
|
+
if (callNode->arg_size() < 2) return;
|
|
1290
1266
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1291
|
-
u32_t size_id = svfir->getValueNode(
|
|
1267
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1292
1268
|
IntervalValue val = as[size_id].getInterval();
|
|
1293
1269
|
if (val.isBottom())
|
|
1294
1270
|
{
|
|
@@ -1300,7 +1276,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1300
1276
|
if (SVFUtil::isa<BufOverflowDetector>(detector))
|
|
1301
1277
|
{
|
|
1302
1278
|
BufOverflowDetector* bufDetector = SVFUtil::cast<BufOverflowDetector>(detector.get());
|
|
1303
|
-
bool isSafe = bufDetector->canSafelyAccessMemory(as,
|
|
1279
|
+
bool isSafe = bufDetector->canSafelyAccessMemory(as, callNode->getArgument(0), val);
|
|
1304
1280
|
if (!isSafe)
|
|
1305
1281
|
{
|
|
1306
1282
|
std::cout << "detect buffer overflow success: " << callNode->toString() << std::endl;
|
|
@@ -1309,7 +1285,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1309
1285
|
else
|
|
1310
1286
|
{
|
|
1311
1287
|
std::string err_msg = "this UNSAFE_BUFACCESS should be a buffer overflow but not detected. Pos: ";
|
|
1312
|
-
err_msg +=
|
|
1288
|
+
err_msg += callNode->getSourceLoc();
|
|
1313
1289
|
std::cerr << err_msg << std::endl;
|
|
1314
1290
|
assert(false);
|
|
1315
1291
|
}
|
|
@@ -1359,7 +1335,6 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1359
1335
|
AbstractState& as = getAbsStateFromTrace(call);
|
|
1360
1336
|
const SVFFunction *fun = SVFUtil::getCallee(call->getCallSite());
|
|
1361
1337
|
assert(fun && "SVFFunction* is nullptr");
|
|
1362
|
-
CallSite cs = SVFUtil::getSVFCallSite(call);
|
|
1363
1338
|
ExtAPIType extType = UNCLASSIFIED;
|
|
1364
1339
|
// get type of mem api
|
|
1365
1340
|
for (const std::string &annotation: fun->getAnnotations())
|
|
@@ -1377,11 +1352,11 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1377
1352
|
{
|
|
1378
1353
|
if (func_map.find(fun->getName()) != func_map.end())
|
|
1379
1354
|
{
|
|
1380
|
-
func_map[fun->getName()](
|
|
1355
|
+
func_map[fun->getName()](call);
|
|
1381
1356
|
}
|
|
1382
1357
|
else
|
|
1383
1358
|
{
|
|
1384
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1359
|
+
u32_t lhsId = svfir->getValueNode(call->getCallSite());
|
|
1385
1360
|
if (as.inVarToAddrsTable(lhsId))
|
|
1386
1361
|
{
|
|
1387
1362
|
|
|
@@ -1396,15 +1371,15 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1396
1371
|
// 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
|
|
1397
1372
|
else if (extType == MEMCPY)
|
|
1398
1373
|
{
|
|
1399
|
-
IntervalValue len = as[svfir->getValueNode(
|
|
1400
|
-
handleMemcpy(as,
|
|
1374
|
+
IntervalValue len = as[svfir->getValueNode(call->getArgument(2))].getInterval();
|
|
1375
|
+
handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
|
|
1401
1376
|
}
|
|
1402
1377
|
else if (extType == MEMSET)
|
|
1403
1378
|
{
|
|
1404
1379
|
// memset dst is arg0, elem is arg1, size is arg2
|
|
1405
|
-
IntervalValue len = as[svfir->getValueNode(
|
|
1406
|
-
IntervalValue elem = as[svfir->getValueNode(
|
|
1407
|
-
handleMemset(as,
|
|
1380
|
+
IntervalValue len = as[svfir->getValueNode(call->getArgument(2))].getInterval();
|
|
1381
|
+
IntervalValue elem = as[svfir->getValueNode(call->getArgument(1))].getInterval();
|
|
1382
|
+
handleMemset(as,call->getArgument(0), elem, len);
|
|
1408
1383
|
}
|
|
1409
1384
|
else if (extType == STRCPY)
|
|
1410
1385
|
{
|
|
@@ -1463,9 +1438,8 @@ void AbstractInterpretation::handleStrcpy(const CallICFGNode *call)
|
|
|
1463
1438
|
// strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
|
|
1464
1439
|
// get the dst and src
|
|
1465
1440
|
AbstractState& as = getAbsStateFromTrace(call);
|
|
1466
|
-
|
|
1467
|
-
const SVFValue*
|
|
1468
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
1441
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
1442
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
1469
1443
|
IntervalValue strLen = getStrlen(as, arg1Val);
|
|
1470
1444
|
// no need to -1, since it has \0 as the last byte
|
|
1471
1445
|
handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
|
|
@@ -1558,9 +1532,8 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
|
|
|
1558
1532
|
const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
|
|
1559
1533
|
if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
|
|
1560
1534
|
{
|
|
1561
|
-
|
|
1562
|
-
const SVFValue*
|
|
1563
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
1535
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
1536
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
1564
1537
|
IntervalValue strLen0 = getStrlen(as, arg0Val);
|
|
1565
1538
|
IntervalValue strLen1 = getStrlen(as, arg1Val);
|
|
1566
1539
|
IntervalValue totalLen = strLen0 + strLen1;
|
|
@@ -1569,10 +1542,9 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
|
|
|
1569
1542
|
}
|
|
1570
1543
|
else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
|
|
1571
1544
|
{
|
|
1572
|
-
|
|
1573
|
-
const SVFValue*
|
|
1574
|
-
const SVFValue*
|
|
1575
|
-
const SVFValue* arg2Val = cs.getArgument(2);
|
|
1545
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
1546
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
1547
|
+
const SVFValue* arg2Val = call->getArgument(2);
|
|
1576
1548
|
IntervalValue arg2Num = as[svfir->getValueNode(arg2Val)].getInterval();
|
|
1577
1549
|
IntervalValue strLen0 = getStrlen(as, arg0Val);
|
|
1578
1550
|
IntervalValue totalLen = strLen0 + arg2Num;
|
package/svf/lib/CFL/CFLAlias.cpp
CHANGED
|
@@ -42,9 +42,9 @@ void CFLAlias::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites, Call
|
|
|
42
42
|
{
|
|
43
43
|
const CallICFGNode* cs = iter->first;
|
|
44
44
|
|
|
45
|
-
if (
|
|
45
|
+
if (cs->isVirtualCall())
|
|
46
46
|
{
|
|
47
|
-
const SVFValue* vtbl =
|
|
47
|
+
const SVFValue* vtbl = cs->getVtablePtr();
|
|
48
48
|
assert(pag->hasValueNode(vtbl));
|
|
49
49
|
NodeID vtblId = pag->getValueNode(vtbl);
|
|
50
50
|
resolveCPPIndCalls(cs, getCFLPts(vtblId), newEdges);
|
|
@@ -58,14 +58,14 @@ void CFLAlias::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites, Call
|
|
|
58
58
|
* Connect formal and actual parameters for indirect callsites
|
|
59
59
|
*/
|
|
60
60
|
|
|
61
|
-
void CFLAlias::connectCaller2CalleeParams(
|
|
61
|
+
void CFLAlias::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F)
|
|
62
62
|
{
|
|
63
63
|
assert(F);
|
|
64
64
|
|
|
65
|
-
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs
|
|
65
|
+
DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs->toString() << " to callee " << *F << "\n");
|
|
66
66
|
|
|
67
|
-
CallICFGNode* callBlockNode =
|
|
68
|
-
RetICFGNode* retBlockNode =
|
|
67
|
+
const CallICFGNode* callBlockNode = cs;
|
|
68
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
69
69
|
|
|
70
70
|
if(SVFUtil::isHeapAllocExtFunViaRet(F) && svfir->callsiteHasRet(retBlockNode))
|
|
71
71
|
{
|
|
@@ -136,15 +136,15 @@ void CFLAlias::connectCaller2CalleeParams(CallSite cs, const SVFFunction* F)
|
|
|
136
136
|
if(csArgIt != csArgEit)
|
|
137
137
|
{
|
|
138
138
|
writeWrnMsg("too many args to non-vararg func.");
|
|
139
|
-
writeWrnMsg("(" + cs
|
|
139
|
+
writeWrnMsg("(" + cs->getSourceLoc() + ")");
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
void CFLAlias::heapAllocatorViaIndCall(
|
|
144
|
+
void CFLAlias::heapAllocatorViaIndCall(const CallICFGNode* cs)
|
|
145
145
|
{
|
|
146
146
|
assert(SVFUtil::getCallee(cs) == nullptr && "not an indirect callsite?");
|
|
147
|
-
RetICFGNode* retBlockNode =
|
|
147
|
+
const RetICFGNode* retBlockNode = cs->getRetICFGNode();
|
|
148
148
|
const PAGNode* cs_return = svfir->getCallSiteRet(retBlockNode);
|
|
149
149
|
NodeID srcret;
|
|
150
150
|
CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
|
|
@@ -155,7 +155,7 @@ void CFLAlias::heapAllocatorViaIndCall(CallSite cs)
|
|
|
155
155
|
else
|
|
156
156
|
{
|
|
157
157
|
NodeID valNode = svfir->addDummyValNode();
|
|
158
|
-
NodeID objNode = svfir->addDummyObjNode(cs
|
|
158
|
+
NodeID objNode = svfir->addDummyObjNode(cs->getCallSite()->getType());
|
|
159
159
|
callsite2DummyValPN.insert(std::make_pair(cs,valNode));
|
|
160
160
|
graph->addCFLNode(valNode, new CFLNode(valNode));
|
|
161
161
|
graph->addCFLNode(objNode, new CFLNode(objNode));
|
|
@@ -175,10 +175,9 @@ bool CFLAlias::updateCallGraph(const CallSiteToFunPtrMap& callsites)
|
|
|
175
175
|
onTheFlyCallGraphSolve(callsites,newEdges);
|
|
176
176
|
for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
|
|
177
177
|
{
|
|
178
|
-
CallSite cs = SVFUtil::getSVFCallSite(it->first);
|
|
179
178
|
for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
|
|
180
179
|
{
|
|
181
|
-
connectCaller2CalleeParams(
|
|
180
|
+
connectCaller2CalleeParams(it->first,*cit);
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
|
|
@@ -81,9 +81,9 @@ OrderedNodeSet& FunptrDDAClient::collectCandidateQueries(SVFIR* p)
|
|
|
81
81
|
for(SVFIR::CallSiteToFunPtrMap::const_iterator it = pag->getIndirectCallsites().begin(),
|
|
82
82
|
eit = pag->getIndirectCallsites().end(); it!=eit; ++it)
|
|
83
83
|
{
|
|
84
|
-
if (
|
|
84
|
+
if (it->first->isVirtualCall())
|
|
85
85
|
{
|
|
86
|
-
const SVFValue* vtblPtr =
|
|
86
|
+
const SVFValue* vtblPtr = it->first->getVtablePtr();
|
|
87
87
|
assert(pag->hasValueNode(vtblPtr) && "not a vtable pointer?");
|
|
88
88
|
NodeID vtblId = pag->getValueNode(vtblPtr);
|
|
89
89
|
addCandidate(vtblId);
|