svf-tools 1.0.984 → 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/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 +51 -66
- 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
|
}
|
|
@@ -965,13 +965,12 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
965
965
|
#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
|
|
966
966
|
auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
|
|
967
967
|
/* run real ext function */ \
|
|
968
|
-
const CallSite& cs = SVFUtil::getSVFCallSite(callNode); \
|
|
969
968
|
AbstractState& as = getAbsStateFromTrace(callNode); \
|
|
970
|
-
u32_t rhs_id = svfir->getValueNode(
|
|
969
|
+
u32_t rhs_id = svfir->getValueNode(callNode->getArgument(0)); \
|
|
971
970
|
if (!as.inVarToValTable(rhs_id)) return; \
|
|
972
971
|
u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
|
|
973
972
|
s32_t res = FUNC_NAME(rhs); \
|
|
974
|
-
u32_t lhsId = svfir->getValueNode(
|
|
973
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite()); \
|
|
975
974
|
as[lhsId] = IntervalValue(res); \
|
|
976
975
|
return; \
|
|
977
976
|
}; \
|
|
@@ -999,7 +998,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
999
998
|
auto sse_svf_assert = [this](const CallICFGNode* callNode)
|
|
1000
999
|
{
|
|
1001
1000
|
checkpoints.erase(callNode);
|
|
1002
|
-
u32_t arg0 = svfir->getValueNode(
|
|
1001
|
+
u32_t arg0 = svfir->getValueNode(callNode->getArgument(0));
|
|
1003
1002
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1004
1003
|
as[arg0].getInterval().meet_with(IntervalValue(1, 1));
|
|
1005
1004
|
if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
|
|
@@ -1017,14 +1016,13 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1017
1016
|
|
|
1018
1017
|
auto svf_print = [&](const CallICFGNode* callNode)
|
|
1019
1018
|
{
|
|
1020
|
-
|
|
1021
|
-
if (cs.arg_size() < 2) return;
|
|
1019
|
+
if (callNode->arg_size() < 2) return;
|
|
1022
1020
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1023
|
-
u32_t num_id = svfir->getValueNode(
|
|
1024
|
-
std::string text = strRead(as,
|
|
1021
|
+
u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
|
|
1022
|
+
std::string text = strRead(as, callNode->getArgument(1));
|
|
1025
1023
|
assert(as.inVarToValTable(num_id) && "print() should pass integer");
|
|
1026
1024
|
IntervalValue itv = as[num_id].getInterval();
|
|
1027
|
-
std::cout << "Text: " << text <<", Value: " <<
|
|
1025
|
+
std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString() << ", PrintVal: " << itv.toString() << std::endl;
|
|
1028
1026
|
return;
|
|
1029
1027
|
};
|
|
1030
1028
|
func_map["svf_print"] = svf_print;
|
|
@@ -1033,11 +1031,10 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1033
1031
|
auto sse_scanf = [&](const CallICFGNode* callNode)
|
|
1034
1032
|
{
|
|
1035
1033
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1036
|
-
const CallSite& cs = SVFUtil::getSVFCallSite(callNode);
|
|
1037
1034
|
//scanf("%d", &data);
|
|
1038
|
-
if (
|
|
1035
|
+
if (callNode->arg_size() < 2) return;
|
|
1039
1036
|
|
|
1040
|
-
u32_t dst_id = svfir->getValueNode(
|
|
1037
|
+
u32_t dst_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1041
1038
|
if (!as.inVarToAddrsTable(dst_id))
|
|
1042
1039
|
{
|
|
1043
1040
|
return;
|
|
@@ -1056,10 +1053,9 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1056
1053
|
auto sse_fscanf = [&](const CallICFGNode* callNode)
|
|
1057
1054
|
{
|
|
1058
1055
|
//fscanf(stdin, "%d", &data);
|
|
1059
|
-
|
|
1060
|
-
if (cs.arg_size() < 3) return;
|
|
1056
|
+
if (callNode->arg_size() < 3) return;
|
|
1061
1057
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1062
|
-
u32_t dst_id = svfir->getValueNode(
|
|
1058
|
+
u32_t dst_id = svfir->getValueNode(callNode->getArgument(2));
|
|
1063
1059
|
if (!as.inVarToAddrsTable(dst_id))
|
|
1064
1060
|
{
|
|
1065
1061
|
}
|
|
@@ -1086,11 +1082,10 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1086
1082
|
|
|
1087
1083
|
auto sse_fread = [&](const CallICFGNode *callNode)
|
|
1088
1084
|
{
|
|
1089
|
-
|
|
1090
|
-
if (cs.arg_size() < 3) return;
|
|
1085
|
+
if (callNode->arg_size() < 3) return;
|
|
1091
1086
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1092
|
-
u32_t block_count_id = svfir->getValueNode(
|
|
1093
|
-
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));
|
|
1094
1089
|
IntervalValue block_count = as[block_count_id].getInterval();
|
|
1095
1090
|
IntervalValue block_size = as[block_size_id].getInterval();
|
|
1096
1091
|
IntervalValue block_byte = block_count * block_size;
|
|
@@ -1104,20 +1099,19 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1104
1099
|
|
|
1105
1100
|
auto sse_snprintf = [&](const CallICFGNode *callNode)
|
|
1106
1101
|
{
|
|
1107
|
-
|
|
1108
|
-
if (cs.arg_size() < 2) return;
|
|
1102
|
+
if (callNode->arg_size() < 2) return;
|
|
1109
1103
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1110
|
-
u32_t size_id = svfir->getValueNode(
|
|
1111
|
-
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));
|
|
1112
1106
|
// get elem size of arg2
|
|
1113
1107
|
u32_t elemSize = 1;
|
|
1114
|
-
if (
|
|
1108
|
+
if (callNode->getArgument(2)->getType()->isArrayTy())
|
|
1115
1109
|
{
|
|
1116
|
-
elemSize = SVFUtil::dyn_cast<SVFArrayType>(
|
|
1110
|
+
elemSize = SVFUtil::dyn_cast<SVFArrayType>(callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
|
|
1117
1111
|
}
|
|
1118
|
-
else if (
|
|
1112
|
+
else if (callNode->getArgument(2)->getType()->isPointerTy())
|
|
1119
1113
|
{
|
|
1120
|
-
elemSize = as.getPointeeElement(svfir->getValueNode(
|
|
1114
|
+
elemSize = as.getPointeeElement(svfir->getValueNode(callNode->getArgument(2)))->getByteSize();
|
|
1121
1115
|
}
|
|
1122
1116
|
else
|
|
1123
1117
|
{
|
|
@@ -1145,10 +1139,9 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1145
1139
|
{
|
|
1146
1140
|
// itoa(num, ch, 10);
|
|
1147
1141
|
// num: int, ch: char*, 10 is decimal
|
|
1148
|
-
|
|
1149
|
-
if (cs.arg_size() < 3) return;
|
|
1142
|
+
if (callNode->arg_size() < 3) return;
|
|
1150
1143
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1151
|
-
u32_t num_id = svfir->getValueNode(
|
|
1144
|
+
u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
|
|
1152
1145
|
|
|
1153
1146
|
u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
|
|
1154
1147
|
std::string snum = std::to_string(num);
|
|
@@ -1159,12 +1152,11 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1159
1152
|
auto sse_strlen = [&](const CallICFGNode *callNode)
|
|
1160
1153
|
{
|
|
1161
1154
|
// check the arg size
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
const SVFValue* strValue = cs.getArgument(0);
|
|
1155
|
+
if (callNode->arg_size() < 1) return;
|
|
1156
|
+
const SVFValue* strValue = callNode->getArgument(0);
|
|
1165
1157
|
AbstractState& as = getAbsStateFromTrace(callNode);
|
|
1166
1158
|
NodeID value_id = svfir->getValueNode(strValue);
|
|
1167
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1159
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
|
|
1168
1160
|
u32_t dst_size = 0;
|
|
1169
1161
|
for (const auto& addr : as[value_id].getAddrs())
|
|
1170
1162
|
{
|
|
@@ -1220,24 +1212,22 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1220
1212
|
auto sse_recv = [&](const CallICFGNode *callNode)
|
|
1221
1213
|
{
|
|
1222
1214
|
// recv(sockfd, buf, len, flags);
|
|
1223
|
-
|
|
1224
|
-
if (cs.arg_size() < 4) return;
|
|
1215
|
+
if (callNode->arg_size() < 4) return;
|
|
1225
1216
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1226
|
-
u32_t len_id = svfir->getValueNode(
|
|
1217
|
+
u32_t len_id = svfir->getValueNode(callNode->getArgument(2));
|
|
1227
1218
|
IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
|
|
1228
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1219
|
+
u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
|
|
1229
1220
|
as[lhsId] = len;
|
|
1230
1221
|
};
|
|
1231
1222
|
func_map["recv"] = sse_recv;
|
|
1232
1223
|
func_map["__recv"] = sse_recv;
|
|
1233
1224
|
auto safe_bufaccess = [&](const CallICFGNode *callNode)
|
|
1234
1225
|
{
|
|
1235
|
-
const CallSite& cs = SVFUtil::getSVFCallSite(callNode);
|
|
1236
1226
|
checkpoints.erase(callNode);
|
|
1237
1227
|
//void SAFE_BUFACCESS(void* data, int size);
|
|
1238
|
-
if (
|
|
1228
|
+
if (callNode->arg_size() < 2) return;
|
|
1239
1229
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1240
|
-
u32_t size_id = svfir->getValueNode(
|
|
1230
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1241
1231
|
IntervalValue val = as[size_id].getInterval();
|
|
1242
1232
|
if (val.isBottom())
|
|
1243
1233
|
{
|
|
@@ -1250,7 +1240,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1250
1240
|
if (SVFUtil::isa<BufOverflowDetector>(detector))
|
|
1251
1241
|
{
|
|
1252
1242
|
BufOverflowDetector* bufDetector = SVFUtil::cast<BufOverflowDetector>(detector.get());
|
|
1253
|
-
bool isSafe = bufDetector->canSafelyAccessMemory(as,
|
|
1243
|
+
bool isSafe = bufDetector->canSafelyAccessMemory(as, callNode->getArgument(0), val);
|
|
1254
1244
|
if (isSafe)
|
|
1255
1245
|
{
|
|
1256
1246
|
std::cout << "safe buffer access success: " << callNode->toString() << std::endl;
|
|
@@ -1259,7 +1249,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1259
1249
|
else
|
|
1260
1250
|
{
|
|
1261
1251
|
std::string err_msg = "this SAFE_BUFACCESS should be a safe access but detected buffer overflow. Pos: ";
|
|
1262
|
-
err_msg +=
|
|
1252
|
+
err_msg += callNode->getSourceLoc();
|
|
1263
1253
|
std::cerr << err_msg << std::endl;
|
|
1264
1254
|
assert(false);
|
|
1265
1255
|
}
|
|
@@ -1270,12 +1260,11 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1270
1260
|
|
|
1271
1261
|
auto unsafe_bufaccess = [&](const CallICFGNode *callNode)
|
|
1272
1262
|
{
|
|
1273
|
-
const CallSite& cs = SVFUtil::getSVFCallSite(callNode);
|
|
1274
1263
|
checkpoints.erase(callNode);
|
|
1275
1264
|
//void UNSAFE_BUFACCESS(void* data, int size);
|
|
1276
|
-
if (
|
|
1265
|
+
if (callNode->arg_size() < 2) return;
|
|
1277
1266
|
AbstractState&as = getAbsStateFromTrace(callNode);
|
|
1278
|
-
u32_t size_id = svfir->getValueNode(
|
|
1267
|
+
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
|
|
1279
1268
|
IntervalValue val = as[size_id].getInterval();
|
|
1280
1269
|
if (val.isBottom())
|
|
1281
1270
|
{
|
|
@@ -1287,7 +1276,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1287
1276
|
if (SVFUtil::isa<BufOverflowDetector>(detector))
|
|
1288
1277
|
{
|
|
1289
1278
|
BufOverflowDetector* bufDetector = SVFUtil::cast<BufOverflowDetector>(detector.get());
|
|
1290
|
-
bool isSafe = bufDetector->canSafelyAccessMemory(as,
|
|
1279
|
+
bool isSafe = bufDetector->canSafelyAccessMemory(as, callNode->getArgument(0), val);
|
|
1291
1280
|
if (!isSafe)
|
|
1292
1281
|
{
|
|
1293
1282
|
std::cout << "detect buffer overflow success: " << callNode->toString() << std::endl;
|
|
@@ -1296,7 +1285,7 @@ void AbstractInterpretation::initExtFunMap()
|
|
|
1296
1285
|
else
|
|
1297
1286
|
{
|
|
1298
1287
|
std::string err_msg = "this UNSAFE_BUFACCESS should be a buffer overflow but not detected. Pos: ";
|
|
1299
|
-
err_msg +=
|
|
1288
|
+
err_msg += callNode->getSourceLoc();
|
|
1300
1289
|
std::cerr << err_msg << std::endl;
|
|
1301
1290
|
assert(false);
|
|
1302
1291
|
}
|
|
@@ -1346,7 +1335,6 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1346
1335
|
AbstractState& as = getAbsStateFromTrace(call);
|
|
1347
1336
|
const SVFFunction *fun = SVFUtil::getCallee(call->getCallSite());
|
|
1348
1337
|
assert(fun && "SVFFunction* is nullptr");
|
|
1349
|
-
CallSite cs = SVFUtil::getSVFCallSite(call);
|
|
1350
1338
|
ExtAPIType extType = UNCLASSIFIED;
|
|
1351
1339
|
// get type of mem api
|
|
1352
1340
|
for (const std::string &annotation: fun->getAnnotations())
|
|
@@ -1368,7 +1356,7 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1368
1356
|
}
|
|
1369
1357
|
else
|
|
1370
1358
|
{
|
|
1371
|
-
u32_t lhsId = svfir->getValueNode(
|
|
1359
|
+
u32_t lhsId = svfir->getValueNode(call->getCallSite());
|
|
1372
1360
|
if (as.inVarToAddrsTable(lhsId))
|
|
1373
1361
|
{
|
|
1374
1362
|
|
|
@@ -1383,15 +1371,15 @@ void AbstractInterpretation::handleExtAPI(const CallICFGNode *call)
|
|
|
1383
1371
|
// 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
|
|
1384
1372
|
else if (extType == MEMCPY)
|
|
1385
1373
|
{
|
|
1386
|
-
IntervalValue len = as[svfir->getValueNode(
|
|
1387
|
-
handleMemcpy(as,
|
|
1374
|
+
IntervalValue len = as[svfir->getValueNode(call->getArgument(2))].getInterval();
|
|
1375
|
+
handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
|
|
1388
1376
|
}
|
|
1389
1377
|
else if (extType == MEMSET)
|
|
1390
1378
|
{
|
|
1391
1379
|
// memset dst is arg0, elem is arg1, size is arg2
|
|
1392
|
-
IntervalValue len = as[svfir->getValueNode(
|
|
1393
|
-
IntervalValue elem = as[svfir->getValueNode(
|
|
1394
|
-
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);
|
|
1395
1383
|
}
|
|
1396
1384
|
else if (extType == STRCPY)
|
|
1397
1385
|
{
|
|
@@ -1450,9 +1438,8 @@ void AbstractInterpretation::handleStrcpy(const CallICFGNode *call)
|
|
|
1450
1438
|
// strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
|
|
1451
1439
|
// get the dst and src
|
|
1452
1440
|
AbstractState& as = getAbsStateFromTrace(call);
|
|
1453
|
-
|
|
1454
|
-
const SVFValue*
|
|
1455
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
1441
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
1442
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
1456
1443
|
IntervalValue strLen = getStrlen(as, arg1Val);
|
|
1457
1444
|
// no need to -1, since it has \0 as the last byte
|
|
1458
1445
|
handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
|
|
@@ -1545,9 +1532,8 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
|
|
|
1545
1532
|
const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
|
|
1546
1533
|
if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
|
|
1547
1534
|
{
|
|
1548
|
-
|
|
1549
|
-
const SVFValue*
|
|
1550
|
-
const SVFValue* arg1Val = cs.getArgument(1);
|
|
1535
|
+
const SVFValue* arg0Val = call->getArgument(0);
|
|
1536
|
+
const SVFValue* arg1Val = call->getArgument(1);
|
|
1551
1537
|
IntervalValue strLen0 = getStrlen(as, arg0Val);
|
|
1552
1538
|
IntervalValue strLen1 = getStrlen(as, arg1Val);
|
|
1553
1539
|
IntervalValue totalLen = strLen0 + strLen1;
|
|
@@ -1556,10 +1542,9 @@ void AbstractInterpretation::handleStrcat(const SVF::CallICFGNode *call)
|
|
|
1556
1542
|
}
|
|
1557
1543
|
else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
|
|
1558
1544
|
{
|
|
1559
|
-
|
|
1560
|
-
const SVFValue*
|
|
1561
|
-
const SVFValue*
|
|
1562
|
-
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);
|
|
1563
1548
|
IntervalValue arg2Num = as[svfir->getValueNode(arg2Val)].getInterval();
|
|
1564
1549
|
IntervalValue strLen0 = getStrlen(as, arg0Val);
|
|
1565
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);
|
package/svf/lib/Graphs/CHG.cpp
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
#include "Graphs/CHG.h"
|
|
31
31
|
#include "Util/SVFUtil.h"
|
|
32
|
+
#include "Graphs/ICFG.h"
|
|
32
33
|
|
|
33
34
|
using namespace SVF;
|
|
34
35
|
using namespace SVFUtil;
|
|
@@ -48,16 +49,16 @@ static bool hasEdge(const CHNode *src, const CHNode *dst,
|
|
|
48
49
|
return false;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
static bool checkArgTypes(
|
|
52
|
+
static bool checkArgTypes(const SVFCallInst* cs, const SVFFunction* fn)
|
|
52
53
|
{
|
|
53
54
|
|
|
54
55
|
// here we skip the first argument (i.e., this pointer)
|
|
55
|
-
u32_t arg_size = (fn->arg_size() > cs
|
|
56
|
+
u32_t arg_size = (fn->arg_size() > cs->arg_size()) ? cs->arg_size(): fn->arg_size();
|
|
56
57
|
if(arg_size > 1)
|
|
57
58
|
{
|
|
58
59
|
for (unsigned i = 1; i < arg_size; i++)
|
|
59
60
|
{
|
|
60
|
-
auto cs_arg = cs
|
|
61
|
+
auto cs_arg = cs->getArgOperand(i);
|
|
61
62
|
auto fn_arg = fn->getArg(i);
|
|
62
63
|
if (cs_arg->getType() != fn_arg->getType())
|
|
63
64
|
{
|
|
@@ -69,6 +70,29 @@ static bool checkArgTypes(CallSite cs, const SVFFunction* fn)
|
|
|
69
70
|
return true;
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
bool CHGraph::csHasVtblsBasedonCHA(const CallICFGNode* cs)
|
|
74
|
+
{
|
|
75
|
+
CallSiteToVTableSetMap::const_iterator it = csToCHAVtblsMap.find(cs->getCallSite());
|
|
76
|
+
return it != csToCHAVtblsMap.end();
|
|
77
|
+
}
|
|
78
|
+
bool CHGraph::csHasVFnsBasedonCHA(const CallICFGNode* cs)
|
|
79
|
+
{
|
|
80
|
+
CallSiteToVFunSetMap::const_iterator it = csToCHAVFnsMap.find(cs->getCallSite());
|
|
81
|
+
return it != csToCHAVFnsMap.end();
|
|
82
|
+
}
|
|
83
|
+
const VTableSet& CHGraph::getCSVtblsBasedonCHA(const CallICFGNode* cs)
|
|
84
|
+
{
|
|
85
|
+
CallSiteToVTableSetMap::const_iterator it = csToCHAVtblsMap.find(cs->getCallSite());
|
|
86
|
+
assert(it != csToCHAVtblsMap.end() && "cs does not have vtabls based on CHA.");
|
|
87
|
+
return it->second;
|
|
88
|
+
}
|
|
89
|
+
const VFunSet& CHGraph::getCSVFsBasedonCHA(const CallICFGNode* cs)
|
|
90
|
+
{
|
|
91
|
+
CallSiteToVFunSetMap::const_iterator it = csToCHAVFnsMap.find(cs->getCallSite());
|
|
92
|
+
assert(it != csToCHAVFnsMap.end() && "cs does not have vfns based on CHA.");
|
|
93
|
+
return it->second;
|
|
94
|
+
}
|
|
95
|
+
|
|
72
96
|
void CHGraph::addEdge(const string className, const string baseClassName,
|
|
73
97
|
CHEdge::CHEDGETYPE edgeType)
|
|
74
98
|
{
|
|
@@ -96,13 +120,13 @@ CHNode *CHGraph::getNode(const string name) const
|
|
|
96
120
|
* Get virtual functions for callsite "cs" based on vtbls (calculated
|
|
97
121
|
* based on pointsto set)
|
|
98
122
|
*/
|
|
99
|
-
void CHGraph::getVFnsFromVtbls(
|
|
123
|
+
void CHGraph::getVFnsFromVtbls(const SVFCallInst* callsite, const VTableSet &vtbls, VFunSet &virtualFunctions)
|
|
100
124
|
{
|
|
101
|
-
|
|
125
|
+
const SVFVirtualCallInst* cs = SVFUtil::cast<SVFVirtualCallInst>(callsite);
|
|
102
126
|
/// get target virtual functions
|
|
103
|
-
size_t idx = cs
|
|
127
|
+
size_t idx = cs->getFunIdxInVtable();
|
|
104
128
|
/// get the function name of the virtual callsite
|
|
105
|
-
string funName = cs
|
|
129
|
+
string funName = cs->getFunNameOfVirtualCall();
|
|
106
130
|
for (const SVFGlobalValue *vt : vtbls)
|
|
107
131
|
{
|
|
108
132
|
const CHNode *child = getNode(vt->getName());
|
|
@@ -114,8 +138,8 @@ void CHGraph::getVFnsFromVtbls(CallSite cs, const VTableSet &vtbls, VFunSet &vir
|
|
|
114
138
|
feit = vfns.end(); fit != feit; ++fit)
|
|
115
139
|
{
|
|
116
140
|
const SVFFunction* callee = *fit;
|
|
117
|
-
if (cs
|
|
118
|
-
(cs
|
|
141
|
+
if (cs->arg_size() == callee->arg_size() ||
|
|
142
|
+
(cs->isVarArg() && callee->isVarArg()))
|
|
119
143
|
{
|
|
120
144
|
|
|
121
145
|
// if argument types do not match
|