svf-tools 1.0.962 → 1.0.964
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/Core/AbstractState.h +3 -0
- package/svf/include/AE/Core/AbstractValue.h +4 -0
- package/svf/include/AE/Core/IntervalValue.h +3 -1
- package/svf/include/AE/Core/NumericValue.h +3 -0
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +3 -3
- package/svf/include/AE/Svfexe/BufOverflowChecker.h +3 -3
- package/svf/include/AE/Svfexe/ICFGSimplification.h +3 -3
- package/svf/include/AE/Svfexe/SVFIR2AbsState.h +3 -3
- package/svf-llvm/lib/ObjTypeInference.cpp +256 -202
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.964",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
* \ \ \ / /
|
|
40
40
|
* ⊥
|
|
41
41
|
*/
|
|
42
|
+
// The implementation is based on
|
|
43
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
44
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
42
45
|
|
|
43
46
|
#ifndef Z3_EXAMPLE_INTERVAL_DOMAIN_H
|
|
44
47
|
#define Z3_EXAMPLE_INTERVAL_DOMAIN_H
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
//
|
|
21
21
|
//===----------------------------------------------------------------------===//
|
|
22
22
|
|
|
23
|
+
// The implementation is based on
|
|
24
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
25
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
26
|
+
|
|
23
27
|
#include "AE/Core/IntervalValue.h"
|
|
24
28
|
#include "AE/Core/AddressValue.h"
|
|
25
29
|
#include "Util/SVFUtil.h"
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
* Author: Jiawei Wang, Xiao Cheng
|
|
27
27
|
*
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
// The implementation is based on
|
|
30
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
31
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
30
32
|
|
|
31
33
|
#ifndef Z3_EXAMPLE_IntervalValue_H
|
|
32
34
|
#define Z3_EXAMPLE_IntervalValue_H
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
* Author: Xiao Cheng, Jiawei Ren
|
|
27
27
|
*
|
|
28
28
|
*/
|
|
29
|
+
// The implementation is based on
|
|
30
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
31
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
29
32
|
|
|
30
33
|
#ifndef SVF_NUMERICVALUE_H
|
|
31
34
|
#define SVF_NUMERICVALUE_H
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
// You should have received a copy of the GNU Affero General Public License
|
|
19
19
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
20
|
//
|
|
21
|
-
// The implementation is based on
|
|
22
|
-
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
23
|
-
// 46th International Conference on Software Engineering. (ICSE24)
|
|
24
21
|
//===----------------------------------------------------------------------===//
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
//
|
|
28
25
|
// Created by Jiawei Wang on 2024/1/10.
|
|
26
|
+
// The implementation is based on
|
|
27
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
28
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
29
29
|
//
|
|
30
30
|
|
|
31
31
|
#include "AE/Core/ICFGWTO.h"
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
// You should have received a copy of the GNU Affero General Public License
|
|
19
19
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
20
|
//
|
|
21
|
-
// The implementation is based on
|
|
22
|
-
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
23
|
-
// 46th International Conference on Software Engineering. (ICSE24)
|
|
24
21
|
//===----------------------------------------------------------------------===//
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
//
|
|
28
25
|
// Created by Jiawei Wang on 2024/1/12.
|
|
26
|
+
// The implementation is based on
|
|
27
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
28
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
29
29
|
//
|
|
30
30
|
|
|
31
31
|
#include "AE/Svfexe/AbstractInterpretation.h"
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
// You should have received a copy of the GNU Affero General Public License
|
|
19
19
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
20
|
//
|
|
21
|
-
// The implementation is based on
|
|
22
|
-
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
23
|
-
// 46th International Conference on Software Engineering. (ICSE24)
|
|
24
21
|
//===----------------------------------------------------------------------===//
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
//
|
|
28
25
|
// Created by Jiawei Wang on 2024/2/25.
|
|
29
26
|
//
|
|
27
|
+
// The implementation is based on
|
|
28
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
29
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
30
30
|
#include "AE/Svfexe/SVFIR2AbsState.h"
|
|
31
31
|
#include "Graphs/ICFG.h"
|
|
32
32
|
|
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
// You should have received a copy of the GNU Affero General Public License
|
|
19
19
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
20
|
//
|
|
21
|
-
// The implementation is based on
|
|
22
|
-
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
23
|
-
// 46th International Conference on Software Engineering. (ICSE24)
|
|
24
21
|
//===----------------------------------------------------------------------===//
|
|
25
22
|
/*
|
|
26
23
|
* SVFIR2AbsState.h
|
|
@@ -29,6 +26,9 @@
|
|
|
29
26
|
* Author: Jiawei Wang, Xiao Cheng
|
|
30
27
|
*
|
|
31
28
|
*/
|
|
29
|
+
// The implementation is based on
|
|
30
|
+
// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
|
|
31
|
+
// 46th International Conference on Software Engineering. (ICSE24)
|
|
32
32
|
|
|
33
33
|
#ifndef Z3_EXAMPLE_SVFIR2ITVEXESTATE_H
|
|
34
34
|
#define Z3_EXAMPLE_SVFIR2ITVEXESTATE_H
|
|
@@ -161,271 +161,325 @@ const Type *ObjTypeInference::inferObjType(const Value *var)
|
|
|
161
161
|
*/
|
|
162
162
|
const Type *ObjTypeInference::fwInferObjType(const Value *var)
|
|
163
163
|
{
|
|
164
|
-
|
|
165
|
-
auto tIt = _valueToType.find(var);
|
|
166
|
-
if (tIt != _valueToType.end())
|
|
164
|
+
if (const AllocaInst *allocaInst = SVFUtil::dyn_cast<AllocaInst>(var))
|
|
167
165
|
{
|
|
168
|
-
|
|
166
|
+
// stack object
|
|
167
|
+
return infersiteToType(allocaInst);
|
|
169
168
|
}
|
|
170
|
-
|
|
171
|
-
// simulate the call stack, the second element indicates whether we should update valueTypes for current value
|
|
172
|
-
FILOWorkList<ValueBoolPair> workList;
|
|
173
|
-
Set<ValueBoolPair> visited;
|
|
174
|
-
workList.push({var, false});
|
|
175
|
-
|
|
176
|
-
while (!workList.empty())
|
|
169
|
+
else if (const GlobalValue *global = SVFUtil::dyn_cast<GlobalValue>(var))
|
|
177
170
|
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
171
|
+
// global object
|
|
172
|
+
return infersiteToType(global);
|
|
173
|
+
}
|
|
174
|
+
else
|
|
175
|
+
{
|
|
176
|
+
// for heap or static object, we forward infer its type
|
|
184
177
|
|
|
185
|
-
|
|
178
|
+
// consult cache
|
|
179
|
+
auto tIt = _valueToType.find(var);
|
|
180
|
+
if (tIt != _valueToType.end())
|
|
186
181
|
{
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
182
|
+
return tIt->second ? tIt->second : defaultType(var);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// simulate the call stack, the second element indicates whether we should update valueTypes for current value
|
|
186
|
+
FILOWorkList<ValueBoolPair> workList;
|
|
187
|
+
Set<ValueBoolPair> visited;
|
|
188
|
+
workList.push({var, false});
|
|
189
|
+
|
|
190
|
+
while (!workList.empty())
|
|
190
191
|
{
|
|
191
|
-
auto
|
|
192
|
-
if (
|
|
192
|
+
auto curPair = workList.pop();
|
|
193
|
+
if (visited.count(curPair))
|
|
194
|
+
continue;
|
|
195
|
+
visited.insert(curPair);
|
|
196
|
+
const Value* curValue = curPair.first;
|
|
197
|
+
bool canUpdate = curPair.second;
|
|
198
|
+
Set<const Value*> infersites;
|
|
199
|
+
|
|
200
|
+
auto insertInferSite = [&infersites,
|
|
201
|
+
&canUpdate](const Value* infersite)
|
|
193
202
|
{
|
|
194
|
-
if (
|
|
203
|
+
if (canUpdate)
|
|
204
|
+
infersites.insert(infersite);
|
|
205
|
+
};
|
|
206
|
+
auto insertInferSitesOrPushWorklist =
|
|
207
|
+
[this, &infersites, &workList, &canUpdate](const auto& pUser)
|
|
208
|
+
{
|
|
209
|
+
auto vIt = _valueToInferSites.find(pUser);
|
|
210
|
+
if (canUpdate)
|
|
195
211
|
{
|
|
196
|
-
|
|
212
|
+
if (vIt != _valueToInferSites.end())
|
|
213
|
+
{
|
|
214
|
+
infersites.insert(vIt->second.begin(),
|
|
215
|
+
vIt->second.end());
|
|
216
|
+
}
|
|
197
217
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
{
|
|
206
|
-
workList.push({curValue, true});
|
|
207
|
-
}
|
|
208
|
-
if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(curValue))
|
|
209
|
-
insertInferSite(gepInst);
|
|
210
|
-
for (const auto it: curValue->users())
|
|
211
|
-
{
|
|
212
|
-
if (const auto *loadInst = SVFUtil::dyn_cast<LoadInst>(it))
|
|
218
|
+
else
|
|
219
|
+
{
|
|
220
|
+
if (vIt == _valueToInferSites.end())
|
|
221
|
+
workList.push({pUser, false});
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
if (!canUpdate && !_valueToInferSites.count(curValue))
|
|
213
225
|
{
|
|
214
|
-
|
|
215
|
-
* infer based on load, e.g.,
|
|
216
|
-
%call = call i8* malloc()
|
|
217
|
-
%1 = bitcast i8* %call to %struct.MyStruct*
|
|
218
|
-
%q = load %struct.MyStruct, %struct.MyStruct* %1
|
|
219
|
-
*/
|
|
220
|
-
insertInferSite(loadInst);
|
|
226
|
+
workList.push({curValue, true});
|
|
221
227
|
}
|
|
222
|
-
|
|
228
|
+
if (const auto* gepInst =
|
|
229
|
+
SVFUtil::dyn_cast<GetElementPtrInst>(curValue))
|
|
230
|
+
insertInferSite(gepInst);
|
|
231
|
+
for (const auto it : curValue->users())
|
|
223
232
|
{
|
|
224
|
-
if (
|
|
233
|
+
if (const auto* loadInst = SVFUtil::dyn_cast<LoadInst>(it))
|
|
225
234
|
{
|
|
226
235
|
/*
|
|
227
|
-
* infer based on
|
|
236
|
+
* infer based on load, e.g.,
|
|
228
237
|
%call = call i8* malloc()
|
|
229
238
|
%1 = bitcast i8* %call to %struct.MyStruct*
|
|
230
|
-
|
|
239
|
+
%q = load %struct.MyStruct, %struct.MyStruct* %1
|
|
231
240
|
*/
|
|
232
|
-
insertInferSite(
|
|
241
|
+
insertInferSite(loadInst);
|
|
233
242
|
}
|
|
234
|
-
else
|
|
243
|
+
else if (const auto* storeInst =
|
|
244
|
+
SVFUtil::dyn_cast<StoreInst>(it))
|
|
235
245
|
{
|
|
236
|
-
|
|
246
|
+
if (storeInst->getPointerOperand() == curValue)
|
|
237
247
|
{
|
|
238
248
|
/*
|
|
239
|
-
*
|
|
249
|
+
* infer based on store (pointer operand), e.g.,
|
|
240
250
|
%call = call i8* malloc()
|
|
241
|
-
|
|
242
|
-
%
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (SVFUtil::isa<LoadInst>(nit))
|
|
246
|
-
insertInferSitesOrPushWorklist(nit);
|
|
251
|
+
%1 = bitcast i8* %call to %struct.MyStruct*
|
|
252
|
+
store %struct.MyStruct .., %struct.MyStruct* %1
|
|
253
|
+
*/
|
|
254
|
+
insertInferSite(storeInst);
|
|
247
255
|
}
|
|
248
|
-
|
|
249
|
-
* infer based on store (value operand) <- gep (result element)
|
|
250
|
-
*/
|
|
251
|
-
if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(
|
|
252
|
-
storeInst->getPointerOperand()))
|
|
256
|
+
else
|
|
253
257
|
{
|
|
258
|
+
for (const auto nit :
|
|
259
|
+
storeInst->getPointerOperand()->users())
|
|
260
|
+
{
|
|
261
|
+
/*
|
|
262
|
+
* propagate across store (value operand) and load
|
|
263
|
+
%call = call i8* malloc()
|
|
264
|
+
store i8* %call, i8** %p
|
|
265
|
+
%q = load i8*, i8** %p
|
|
266
|
+
..infer based on %q..
|
|
267
|
+
*/
|
|
268
|
+
if (SVFUtil::isa<LoadInst>(nit))
|
|
269
|
+
insertInferSitesOrPushWorklist(nit);
|
|
270
|
+
}
|
|
254
271
|
/*
|
|
255
|
-
|
|
256
|
-
%2 = bitcast i8* %call1 to %struct.MyStruct*, !dbg !41
|
|
257
|
-
%3 = load %struct.MyStruct*, %struct.MyStruct** %p, align 8, !dbg !42
|
|
258
|
-
%next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %3, i32 0, i32 1, !dbg !43
|
|
259
|
-
store %struct.MyStruct* %2, %struct.MyStruct** %next, align 8, !dbg !44
|
|
260
|
-
%5 = load %struct.MyStruct*, %struct.MyStruct** %p, align 8, !dbg !48
|
|
261
|
-
%next3 = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %5, i32 0, i32 1, !dbg !49
|
|
262
|
-
%6 = load %struct.MyStruct*, %struct.MyStruct** %next3, align 8, !dbg !49
|
|
263
|
-
infer site -> %f1 = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %6, i32 0, i32 0, !dbg !50
|
|
272
|
+
* infer based on store (value operand) <- gep (result element)
|
|
264
273
|
*/
|
|
265
|
-
const
|
|
266
|
-
|
|
274
|
+
if (const auto* gepInst =
|
|
275
|
+
SVFUtil::dyn_cast<GetElementPtrInst>(
|
|
276
|
+
storeInst->getPointerOperand()))
|
|
267
277
|
{
|
|
268
|
-
|
|
278
|
+
/*
|
|
279
|
+
%call1 = call i8* @TYPE_MALLOC(i32 noundef 16, i32
|
|
280
|
+
noundef 2), !dbg !39 %2 = bitcast i8* %call1 to
|
|
281
|
+
%struct.MyStruct*, !dbg !41 %3 = load
|
|
282
|
+
%struct.MyStruct*, %struct.MyStruct** %p, align 8,
|
|
283
|
+
!dbg !42 %next = getelementptr inbounds
|
|
284
|
+
%struct.MyStruct, %struct.MyStruct* %3, i32 0, i32
|
|
285
|
+
1, !dbg !43 store %struct.MyStruct* %2,
|
|
286
|
+
%struct.MyStruct** %next, align 8, !dbg !44 %5 =
|
|
287
|
+
load %struct.MyStruct*, %struct.MyStruct** %p,
|
|
288
|
+
align 8, !dbg !48 %next3 = getelementptr inbounds
|
|
289
|
+
%struct.MyStruct, %struct.MyStruct* %5, i32 0, i32
|
|
290
|
+
1, !dbg !49 %6 = load %struct.MyStruct*,
|
|
291
|
+
%struct.MyStruct** %next3, align 8, !dbg !49 infer
|
|
292
|
+
site -> %f1 = getelementptr inbounds
|
|
293
|
+
%struct.MyStruct, %struct.MyStruct* %6, i32 0, i32
|
|
294
|
+
0, !dbg !50
|
|
295
|
+
*/
|
|
296
|
+
const Value* gepBase = gepInst->getPointerOperand();
|
|
297
|
+
if (const auto* load =
|
|
298
|
+
SVFUtil::dyn_cast<LoadInst>(gepBase))
|
|
269
299
|
{
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
for (const auto gepUse: loadUse->users())
|
|
300
|
+
for (const auto loadUse :
|
|
301
|
+
load->getPointerOperand()->users())
|
|
273
302
|
{
|
|
274
|
-
if (
|
|
275
|
-
|
|
303
|
+
if (loadUse == load ||
|
|
304
|
+
!SVFUtil::isa<LoadInst>(loadUse))
|
|
305
|
+
continue;
|
|
306
|
+
for (const auto gepUse : loadUse->users())
|
|
276
307
|
{
|
|
277
|
-
if (SVFUtil::isa<
|
|
308
|
+
if (!SVFUtil::isa<GetElementPtrInst>(
|
|
309
|
+
gepUse))
|
|
310
|
+
continue;
|
|
311
|
+
for (const auto loadUse2 :
|
|
312
|
+
gepUse->users())
|
|
278
313
|
{
|
|
279
|
-
|
|
314
|
+
if (SVFUtil::isa<LoadInst>(
|
|
315
|
+
loadUse2))
|
|
316
|
+
{
|
|
317
|
+
insertInferSitesOrPushWorklist(
|
|
318
|
+
loadUse2);
|
|
319
|
+
}
|
|
280
320
|
}
|
|
281
321
|
}
|
|
282
322
|
}
|
|
283
323
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
{
|
|
287
|
-
/*
|
|
288
|
-
%2 = alloca %struct.ll, align 8
|
|
289
|
-
store i32 0, ptr %1, align 4
|
|
290
|
-
%3 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #2
|
|
291
|
-
%4 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
|
|
292
|
-
store ptr %3, ptr %4, align 8
|
|
293
|
-
%5 = getelementptr inbounds %struct.ll, ptr %2, i32 0, i32 1
|
|
294
|
-
%6 = load ptr, ptr %5, align 8
|
|
295
|
-
%7 = getelementptr inbounds %struct.ll, ptr %6, i32 0, i32 0
|
|
296
|
-
*/
|
|
297
|
-
for (const auto gepUse: alloc->users())
|
|
324
|
+
else if (const auto* alloc =
|
|
325
|
+
SVFUtil::dyn_cast<AllocaInst>(gepBase))
|
|
298
326
|
{
|
|
299
|
-
|
|
300
|
-
|
|
327
|
+
/*
|
|
328
|
+
%2 = alloca %struct.ll, align 8
|
|
329
|
+
store i32 0, ptr %1, align 4
|
|
330
|
+
%3 = call noalias noundef nonnull ptr
|
|
331
|
+
@_Znwm(i64 noundef 16) #2 %4 = getelementptr
|
|
332
|
+
inbounds %struct.ll, ptr %2, i32 0, i32 1
|
|
333
|
+
store ptr %3, ptr %4, align 8
|
|
334
|
+
%5 = getelementptr inbounds %struct.ll, ptr
|
|
335
|
+
%2, i32 0, i32 1 %6 = load ptr, ptr %5, align
|
|
336
|
+
8 %7 = getelementptr inbounds %struct.ll, ptr
|
|
337
|
+
%6, i32 0, i32 0
|
|
338
|
+
*/
|
|
339
|
+
for (const auto gepUse : alloc->users())
|
|
301
340
|
{
|
|
302
|
-
if (SVFUtil::isa<
|
|
341
|
+
if (!SVFUtil::isa<GetElementPtrInst>(
|
|
342
|
+
gepUse))
|
|
343
|
+
continue;
|
|
344
|
+
for (const auto loadUse2 : gepUse->users())
|
|
303
345
|
{
|
|
304
|
-
|
|
346
|
+
if (SVFUtil::isa<LoadInst>(loadUse2))
|
|
347
|
+
{
|
|
348
|
+
insertInferSitesOrPushWorklist(
|
|
349
|
+
loadUse2);
|
|
350
|
+
}
|
|
305
351
|
}
|
|
306
352
|
}
|
|
307
353
|
}
|
|
308
354
|
}
|
|
309
355
|
}
|
|
310
356
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
else if (const auto *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(it))
|
|
314
|
-
{
|
|
315
|
-
/*
|
|
316
|
-
* infer based on gep (pointer operand)
|
|
317
|
-
%call = call i8* malloc()
|
|
318
|
-
%1 = bitcast i8* %call to %struct.MyStruct*
|
|
319
|
-
%next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %1, i32 0..
|
|
320
|
-
*/
|
|
321
|
-
if (gepInst->getPointerOperand() == curValue)
|
|
322
|
-
insertInferSite(gepInst);
|
|
323
|
-
}
|
|
324
|
-
else if (const auto *bitcast = SVFUtil::dyn_cast<BitCastInst>(it))
|
|
325
|
-
{
|
|
326
|
-
// continue on bitcast
|
|
327
|
-
insertInferSitesOrPushWorklist(bitcast);
|
|
328
|
-
}
|
|
329
|
-
else if (const auto *phiNode = SVFUtil::dyn_cast<PHINode>(it))
|
|
330
|
-
{
|
|
331
|
-
// continue on bitcast
|
|
332
|
-
insertInferSitesOrPushWorklist(phiNode);
|
|
333
|
-
}
|
|
334
|
-
else if (const auto *retInst = SVFUtil::dyn_cast<ReturnInst>(it))
|
|
335
|
-
{
|
|
336
|
-
/*
|
|
337
|
-
* propagate from return to caller
|
|
338
|
-
Function Attrs: noinline nounwind optnone uwtable
|
|
339
|
-
define dso_local i8* @malloc_wrapper() #0 !dbg !22 {
|
|
340
|
-
entry:
|
|
341
|
-
%call = call i8* @malloc(i32 noundef 16), !dbg !25
|
|
342
|
-
ret i8* %call, !dbg !26
|
|
343
|
-
}
|
|
344
|
-
%call = call i8* @malloc_wrapper()
|
|
345
|
-
..infer based on %call..
|
|
346
|
-
*/
|
|
347
|
-
for (const auto callsite: retInst->getFunction()->users())
|
|
357
|
+
else if (const auto* gepInst =
|
|
358
|
+
SVFUtil::dyn_cast<GetElementPtrInst>(it))
|
|
348
359
|
{
|
|
349
|
-
|
|
360
|
+
/*
|
|
361
|
+
* infer based on gep (pointer operand)
|
|
362
|
+
%call = call i8* malloc()
|
|
363
|
+
%1 = bitcast i8* %call to %struct.MyStruct*
|
|
364
|
+
%next = getelementptr inbounds %struct.MyStruct,
|
|
365
|
+
%struct.MyStruct* %1, i32 0..
|
|
366
|
+
*/
|
|
367
|
+
if (gepInst->getPointerOperand() == curValue)
|
|
368
|
+
insertInferSite(gepInst);
|
|
369
|
+
}
|
|
370
|
+
else if (const auto* bitcast =
|
|
371
|
+
SVFUtil::dyn_cast<BitCastInst>(it))
|
|
372
|
+
{
|
|
373
|
+
// continue on bitcast
|
|
374
|
+
insertInferSitesOrPushWorklist(bitcast);
|
|
375
|
+
}
|
|
376
|
+
else if (const auto* phiNode = SVFUtil::dyn_cast<PHINode>(it))
|
|
377
|
+
{
|
|
378
|
+
// continue on bitcast
|
|
379
|
+
insertInferSitesOrPushWorklist(phiNode);
|
|
380
|
+
}
|
|
381
|
+
else if (const auto* retInst =
|
|
382
|
+
SVFUtil::dyn_cast<ReturnInst>(it))
|
|
383
|
+
{
|
|
384
|
+
/*
|
|
385
|
+
* propagate from return to caller
|
|
386
|
+
Function Attrs: noinline nounwind optnone uwtable
|
|
387
|
+
define dso_local i8* @malloc_wrapper() #0 !dbg !22 {
|
|
388
|
+
entry:
|
|
389
|
+
%call = call i8* @malloc(i32 noundef 16), !dbg !25
|
|
390
|
+
ret i8* %call, !dbg !26
|
|
391
|
+
}
|
|
392
|
+
%call = call i8* @malloc_wrapper()
|
|
393
|
+
..infer based on %call..
|
|
394
|
+
*/
|
|
395
|
+
for (const auto callsite : retInst->getFunction()->users())
|
|
350
396
|
{
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
397
|
+
if (const auto* callBase =
|
|
398
|
+
SVFUtil::dyn_cast<CallBase>(callsite))
|
|
399
|
+
{
|
|
400
|
+
// skip function as parameter
|
|
401
|
+
// e.g., call void @foo(%struct.ssl_ctx_st* %9, i32 (i8*, i32, i32, i8*)* @passwd_callback)
|
|
402
|
+
if (callBase->getCalledFunction() !=
|
|
403
|
+
retInst->getFunction())
|
|
404
|
+
continue;
|
|
405
|
+
insertInferSitesOrPushWorklist(callBase);
|
|
406
|
+
}
|
|
355
407
|
}
|
|
356
408
|
}
|
|
357
|
-
|
|
358
|
-
else if (const auto *callBase = SVFUtil::dyn_cast<CallBase>(it))
|
|
359
|
-
{
|
|
360
|
-
/*
|
|
361
|
-
* propagate from callsite to callee
|
|
362
|
-
%call = call i8* @malloc(i32 noundef 16)
|
|
363
|
-
%0 = bitcast i8* %call to %struct.Node*, !dbg !43
|
|
364
|
-
call void @foo(%struct.Node* noundef %0), !dbg !45
|
|
365
|
-
|
|
366
|
-
define dso_local void @foo(%struct.Node* noundef %param) #0 !dbg !22 {...}
|
|
367
|
-
..infer based on the formal param %param..
|
|
368
|
-
*/
|
|
369
|
-
// skip global function value -> callsite
|
|
370
|
-
// e.g., def @foo() -> call @foo()
|
|
371
|
-
// we don't skip function as parameter, e.g., def @foo() -> call @bar(..., @foo)
|
|
372
|
-
if (SVFUtil::isa<Function>(curValue) && curValue == callBase->getCalledFunction()) continue;
|
|
373
|
-
// skip indirect call
|
|
374
|
-
// e.g., %0 = ... -> call %0(...)
|
|
375
|
-
if (!callBase->hasArgument(curValue)) continue;
|
|
376
|
-
if (Function *calleeFunc = callBase->getCalledFunction())
|
|
409
|
+
else if (const auto* callBase = SVFUtil::dyn_cast<CallBase>(it))
|
|
377
410
|
{
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
|
|
411
|
+
/*
|
|
412
|
+
* propagate from callsite to callee
|
|
413
|
+
%call = call i8* @malloc(i32 noundef 16)
|
|
414
|
+
%0 = bitcast i8* %call to %struct.Node*, !dbg !43
|
|
415
|
+
call void @foo(%struct.Node* noundef %0), !dbg !45
|
|
416
|
+
|
|
417
|
+
define dso_local void @foo(%struct.Node* noundef %param)
|
|
418
|
+
#0 !dbg !22 {...}
|
|
419
|
+
..infer based on the formal param %param..
|
|
420
|
+
*/
|
|
421
|
+
// skip global function value -> callsite
|
|
422
|
+
// e.g., def @foo() -> call @foo()
|
|
423
|
+
// we don't skip function as parameter, e.g., def @foo() -> call @bar(..., @foo)
|
|
424
|
+
if (SVFUtil::isa<Function>(curValue) &&
|
|
425
|
+
curValue == callBase->getCalledFunction())
|
|
426
|
+
continue;
|
|
427
|
+
// skip indirect call
|
|
428
|
+
// e.g., %0 = ... -> call %0(...)
|
|
429
|
+
if (!callBase->hasArgument(curValue))
|
|
430
|
+
continue;
|
|
431
|
+
if (Function* calleeFunc = callBase->getCalledFunction())
|
|
391
432
|
{
|
|
392
|
-
|
|
393
|
-
for (
|
|
433
|
+
u32_t pos = getArgPosInCall(callBase, curValue);
|
|
434
|
+
// for varargs function, we cannot directly get the value-flow between actual and formal args e.g., consider the following vararg function @callee 1: call void @callee(%arg) 2: define dso_local i32 @callee(...) #0 !dbg !17 { 3: ....... 4: %5 = load i32, ptr %vaarg.addr, align 4, !dbg !55 5: .......
|
|
435
|
+
// 6: }
|
|
436
|
+
// it is challenging to precisely identify the forward value-flow of %arg (Line 2) because the function definition of callee (Line 2) does not have any formal args related to the actual arg %arg therefore we track all possible instructions like ``load i32, ptr %vaarg.addr''
|
|
437
|
+
if (calleeFunc->isVarArg())
|
|
394
438
|
{
|
|
395
|
-
|
|
439
|
+
// conservatively track all var args
|
|
440
|
+
for (auto& I : instructions(calleeFunc))
|
|
396
441
|
{
|
|
397
|
-
|
|
398
|
-
|
|
442
|
+
if (auto* load =
|
|
443
|
+
llvm::dyn_cast<llvm::LoadInst>(&I))
|
|
399
444
|
{
|
|
400
|
-
|
|
445
|
+
llvm::Value* loadPointer =
|
|
446
|
+
load->getPointerOperand();
|
|
447
|
+
if (loadPointer->getName().compare(
|
|
448
|
+
"vaarg.addr") == 0)
|
|
449
|
+
{
|
|
450
|
+
insertInferSitesOrPushWorklist(load);
|
|
451
|
+
}
|
|
401
452
|
}
|
|
402
453
|
}
|
|
403
454
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
455
|
+
else if (!calleeFunc->isDeclaration())
|
|
456
|
+
{
|
|
457
|
+
insertInferSitesOrPushWorklist(
|
|
458
|
+
calleeFunc->getArg(pos));
|
|
459
|
+
}
|
|
408
460
|
}
|
|
409
461
|
}
|
|
410
462
|
}
|
|
463
|
+
if (canUpdate)
|
|
464
|
+
{
|
|
465
|
+
Set<const Type*> types;
|
|
466
|
+
std::transform(infersites.begin(), infersites.end(),
|
|
467
|
+
std::inserter(types, types.begin()),
|
|
468
|
+
infersiteToType);
|
|
469
|
+
_valueToInferSites[curValue] = SVFUtil::move(infersites);
|
|
470
|
+
_valueToType[curValue] = selectLargestSizedType(types);
|
|
471
|
+
}
|
|
411
472
|
}
|
|
412
|
-
|
|
473
|
+
const Type* type = _valueToType[var];
|
|
474
|
+
if (type == nullptr)
|
|
413
475
|
{
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
_valueToInferSites[curValue] = SVFUtil::move(infersites);
|
|
418
|
-
_valueToType[curValue] = selectLargestSizedType(types);
|
|
476
|
+
type = defaultType(var);
|
|
477
|
+
WARN_MSG("Using default type, trace ID is " +
|
|
478
|
+
std::to_string(traceId) + ":" + dumpValueAndDbgInfo(var));
|
|
419
479
|
}
|
|
480
|
+
ABORT_IFNOT(type, "type cannot be a null ptr");
|
|
481
|
+
return type;
|
|
420
482
|
}
|
|
421
|
-
const Type *type = _valueToType[var];
|
|
422
|
-
if (type == nullptr)
|
|
423
|
-
{
|
|
424
|
-
type = defaultType(var);
|
|
425
|
-
WARN_MSG("Using default type, trace ID is " + std::to_string(traceId) + ":" + dumpValueAndDbgInfo(var));
|
|
426
|
-
}
|
|
427
|
-
ABORT_IFNOT(type, "type cannot be a null ptr");
|
|
428
|
-
return type;
|
|
429
483
|
}
|
|
430
484
|
|
|
431
485
|
/*!
|