svf-tools 1.0.1083 → 1.0.1084
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 +33 -15
- package/svf/include/AE/Core/AddressValue.h +15 -22
- package/svf/include/AE/Svfexe/AEDetector.h +114 -1
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +20 -13
- package/svf/include/Util/Options.h +2 -0
- package/svf/lib/AE/Core/AbstractState.cpp +8 -2
- package/svf/lib/AE/Svfexe/AEDetector.cpp +183 -21
- package/svf/lib/AE/Svfexe/AbsExtAPI.cpp +32 -6
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +30 -8
- package/svf/lib/Util/Options.cpp +2 -0
- package/svf-llvm/tools/AE/ae.cpp +2 -0
- package/SVF-doxygen/doxygen.config +0 -2548
- package/SVF-doxygen/wiki/PAG.png +0 -0
- package/SVF-doxygen/wiki/andersen.png +0 -0
- package/SVF-doxygen/wiki/callgraph.png +0 -0
- package/SVF-doxygen/wiki/consG.png +0 -0
- package/SVF-doxygen/wiki/cpu2000-flto +0 -432
- package/SVF-doxygen/wiki/cpu2006-flto +0 -417
- package/SVF-doxygen/wiki/cpu2017-wllvm.cfg +0 -999
- package/SVF-doxygen/wiki/database.png +0 -0
- package/SVF-doxygen/wiki/framework.png +0 -0
- package/SVF-doxygen/wiki/help.png +0 -0
- package/SVF-doxygen/wiki/icfg.png +0 -0
- package/SVF-doxygen/wiki/mssa-cha.png +0 -0
- package/SVF-doxygen/wiki/pagedge.png +0 -0
- package/SVF-doxygen/wiki/pagnode.png +0 -0
- package/SVF-doxygen/wiki/pt.png +0 -0
- package/SVF-doxygen/wiki/setupcmake.png +0 -0
- package/SVF-doxygen/wiki/setupconfiguration.png +0 -0
- package/SVF-doxygen/wiki/setupdashboard.png +0 -0
- package/SVF-doxygen/wiki/setupdebug.png +0 -0
- package/SVF-doxygen/wiki/setupenv.png +0 -0
- package/SVF-doxygen/wiki/startup.png +0 -0
- package/SVF-doxygen/wiki/svf-stat.pdf +0 -0
- package/SVF-doxygen/wiki/svfg-framework.png +0 -0
- package/SVF-doxygen/wiki/svfg.png +0 -0
- package/SVF-doxygen/wiki/svfg_opt.png +0 -0
- package/SVF-doxygen/wiki/svfgedge-cha.png +0 -0
- package/SVF-doxygen/wiki/svfgnode-cha.png +0 -0
- package/SVF-doxygen/wiki/svfpic/README.md +0 -6
- package/SVF-doxygen/wiki/svfpic/ass-1debug1.png +0 -0
- package/SVF-doxygen/wiki/svfpic/ass-1debug2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/build.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/cmd.png +0 -0
- package/SVF-doxygen/wiki/svfpic/connect1.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/connect2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/connect3.png +0 -0
- package/SVF-doxygen/wiki/svfpic/connect4.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/connect5.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/connect6.png +0 -0
- package/SVF-doxygen/wiki/svfpic/connect7.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/continue.png +0 -0
- package/SVF-doxygen/wiki/svfpic/debug-new.png +0 -0
- package/SVF-doxygen/wiki/svfpic/debug-new2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/debug1.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/debug2.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/debug3.png +0 -0
- package/SVF-doxygen/wiki/svfpic/debug4.png +0 -0
- package/SVF-doxygen/wiki/svfpic/debug5.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/debug6.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/docker_sys_requirement.png +0 -0
- package/SVF-doxygen/wiki/svfpic/docker_sys_requirements.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuild.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuild2.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuild3.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuild4.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuild5.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerbuildimage.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockercmd.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockercmd2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockercontainer.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb1.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb10.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb2.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb3.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb4.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb5.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb6.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb7.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb8.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerdb9.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerfinshbuilt.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerimage.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockernameImage.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerpull.png +0 -0
- package/SVF-doxygen/wiki/svfpic/dockerpull2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/download.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/extension1.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/extension2.jpeg +0 -0
- package/SVF-doxygen/wiki/svfpic/graphviz.png +0 -0
- package/SVF-doxygen/wiki/svfpic/hellodb.png +0 -0
- package/SVF-doxygen/wiki/svfpic/hellodb2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/hviz_0.png +0 -0
- package/SVF-doxygen/wiki/svfpic/hviz_1.png +0 -0
- package/SVF-doxygen/wiki/svfpic/hviz_2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/installC:C++Ext.png +0 -0
- package/SVF-doxygen/wiki/svfpic/installCMakeExt.png +0 -0
- package/SVF-doxygen/wiki/svfpic/installRCext.png +0 -0
- package/SVF-doxygen/wiki/svfpic/installdockerext.png +0 -0
- package/SVF-doxygen/wiki/svfpic/launch1.png +0 -0
- package/SVF-doxygen/wiki/svfpic/openfile.png +0 -0
- package/SVF-doxygen/wiki/svfpic/pathfolder.png +0 -0
- package/SVF-doxygen/wiki/svfpic/restart.png +0 -0
- package/SVF-doxygen/wiki/svfpic/rundocker.png +0 -0
- package/SVF-doxygen/wiki/svfpic/runinCLI.png +0 -0
- package/SVF-doxygen/wiki/svfpic/screen.png +0 -0
- package/SVF-doxygen/wiki/svfpic/settings1.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/settings2.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/settings3.jpg +0 -0
- package/SVF-doxygen/wiki/svfpic/shortlists.png +0 -0
- package/SVF-doxygen/wiki/svfpic/start.png +0 -0
- package/SVF-doxygen/wiki/svfpic/start1.png +0 -0
- package/SVF-doxygen/wiki/svfpic/update0.png +0 -0
- package/SVF-doxygen/wiki/svfpic/verify_docker.png +0 -0
- package/SVF-doxygen/wiki/svfpic/vs_entry_window.png +0 -0
- package/SVF-doxygen/wiki/svfpic/wsl.png +0 -0
- package/SVF-doxygen/wiki/svfpic/wsl_1.png +0 -0
- package/SVF-doxygen/wiki/svfpic/wsl_2.png +0 -0
- package/SVF-doxygen/wiki/svfpic/wsl_3.png +0 -0
- package/SVF-doxygen/wiki/tools.png +0 -0
- package/SVF-doxygen/wiki/users.png +0 -0
- package/SVF-doxygen/wiki/vm1.png +0 -0
- package/SVF-doxygen/wiki/vm2.png +0 -0
- package/SVF-doxygen/wiki/vm3.png +0 -0
- package/SVF-doxygen/wiki/vm4.png +0 -0
- package/SVF-doxygen/wiki/vm5.png +0 -0
- package/SVF-doxygen/wiki/vscode_build_tasks.png +0 -0
- package/SVF-doxygen/wiki/vscode_cpp_extension.png +0 -0
- package/SVF-doxygen/wiki/vscode_debug_list.png +0 -0
- package/SVF-doxygen/wiki/vscode_dir_structure.png +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1084",
|
|
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": {
|
|
@@ -61,8 +61,9 @@ class AbstractState
|
|
|
61
61
|
friend class RelationSolver;
|
|
62
62
|
public:
|
|
63
63
|
typedef Map<u32_t, AbstractValue> VarToAbsValMap;
|
|
64
|
-
|
|
65
64
|
typedef VarToAbsValMap AddrToAbsValMap;
|
|
65
|
+
Set<NodeID> _freedAddrs;
|
|
66
|
+
|
|
66
67
|
|
|
67
68
|
public:
|
|
68
69
|
/// default constructor
|
|
@@ -73,7 +74,7 @@ public:
|
|
|
73
74
|
AbstractState(VarToAbsValMap&_varToValMap, AddrToAbsValMap&_locToValMap) : _varToAbsVal(_varToValMap), _addrToAbsVal(_locToValMap) {}
|
|
74
75
|
|
|
75
76
|
/// copy constructor
|
|
76
|
-
AbstractState(const AbstractState&rhs) : _varToAbsVal(rhs.getVarToVal()), _addrToAbsVal(rhs.getLocToVal())
|
|
77
|
+
AbstractState(const AbstractState&rhs) : _freedAddrs(rhs._freedAddrs), _varToAbsVal(rhs.getVarToVal()), _addrToAbsVal(rhs.getLocToVal())
|
|
77
78
|
{
|
|
78
79
|
|
|
79
80
|
}
|
|
@@ -110,15 +111,10 @@ public:
|
|
|
110
111
|
return AddressValue::isVirtualMemAddress(val);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
/// Return the internal index if
|
|
114
|
-
|
|
115
|
-
{
|
|
116
|
-
return AddressValue::getInternalID(idx);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static inline bool isNullPtr(u32_t addr)
|
|
114
|
+
/// Return the internal index if addr is an address otherwise return the value of idx
|
|
115
|
+
inline u32_t getIDFromAddr(u32_t addr)
|
|
120
116
|
{
|
|
121
|
-
return
|
|
117
|
+
return _freedAddrs.count(addr) ? AddressValue::getInternalID(InvalidMemAddr) : AddressValue::getInternalID(addr);
|
|
122
118
|
}
|
|
123
119
|
|
|
124
120
|
AbstractState&operator=(const AbstractState&rhs)
|
|
@@ -127,6 +123,7 @@ public:
|
|
|
127
123
|
{
|
|
128
124
|
_varToAbsVal = rhs._varToAbsVal;
|
|
129
125
|
_addrToAbsVal = rhs._addrToAbsVal;
|
|
126
|
+
_freedAddrs = rhs._freedAddrs;
|
|
130
127
|
}
|
|
131
128
|
return *this;
|
|
132
129
|
}
|
|
@@ -145,6 +142,7 @@ public:
|
|
|
145
142
|
{
|
|
146
143
|
_varToAbsVal = std::move(rhs._varToAbsVal);
|
|
147
144
|
_addrToAbsVal = std::move(rhs._addrToAbsVal);
|
|
145
|
+
_freedAddrs = std::move(rhs._freedAddrs);
|
|
148
146
|
}
|
|
149
147
|
return *this;
|
|
150
148
|
}
|
|
@@ -184,6 +182,17 @@ public:
|
|
|
184
182
|
return inv;
|
|
185
183
|
}
|
|
186
184
|
|
|
185
|
+
static inline bool isNullMem(u32_t addr)
|
|
186
|
+
{
|
|
187
|
+
return AddressValue::getInternalID(addr) == NullMemAddr;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static inline bool isInvalidMem(u32_t addr)
|
|
191
|
+
{
|
|
192
|
+
return AddressValue::getInternalID(addr) == InvalidMemAddr;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
187
196
|
protected:
|
|
188
197
|
VarToAbsValMap _varToAbsVal; ///< Map a variable (symbol) to its abstract value
|
|
189
198
|
AddrToAbsValMap
|
|
@@ -279,10 +288,19 @@ public:
|
|
|
279
288
|
/// domain join with other, important! other widen this.
|
|
280
289
|
void joinWith(const AbstractState&other);
|
|
281
290
|
|
|
282
|
-
|
|
283
291
|
/// domain meet with other, important! other widen this.
|
|
284
292
|
void meetWith(const AbstractState&other);
|
|
285
293
|
|
|
294
|
+
void addToFreedAddrs(NodeID addr) {
|
|
295
|
+
_freedAddrs.insert(addr);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
bool isFreedMem(u32_t addr) const
|
|
299
|
+
{
|
|
300
|
+
return _freedAddrs.find(addr) != _freedAddrs.end();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
286
304
|
/**
|
|
287
305
|
* if this NodeID in SVFIR is a pointer, get the pointee type
|
|
288
306
|
* e.g arr = (int*) malloc(10*sizeof(int))
|
|
@@ -299,20 +317,19 @@ public:
|
|
|
299
317
|
inline void store(u32_t addr, const AbstractValue &val)
|
|
300
318
|
{
|
|
301
319
|
assert(isVirtualMemAddress(addr) && "not virtual address?");
|
|
302
|
-
|
|
303
|
-
|
|
320
|
+
u32_t objId = getIDFromAddr(addr);
|
|
321
|
+
if (isNullMem(addr)) return;
|
|
304
322
|
_addrToAbsVal[objId] = val;
|
|
305
323
|
}
|
|
306
324
|
|
|
307
325
|
inline virtual AbstractValue &load(u32_t addr)
|
|
308
326
|
{
|
|
309
327
|
assert(isVirtualMemAddress(addr) && "not virtual address?");
|
|
310
|
-
u32_t objId =
|
|
328
|
+
u32_t objId = getIDFromAddr(addr);
|
|
311
329
|
return _addrToAbsVal[objId];
|
|
312
330
|
|
|
313
331
|
}
|
|
314
332
|
|
|
315
|
-
|
|
316
333
|
void printAbstractState() const;
|
|
317
334
|
|
|
318
335
|
std::string toString() const
|
|
@@ -396,6 +413,7 @@ public:
|
|
|
396
413
|
{
|
|
397
414
|
_addrToAbsVal.clear();
|
|
398
415
|
_varToAbsVal.clear();
|
|
416
|
+
_freedAddrs.clear();
|
|
399
417
|
}
|
|
400
418
|
|
|
401
419
|
};
|
|
@@ -32,8 +32,12 @@
|
|
|
32
32
|
|
|
33
33
|
#define AddressMask 0x7f000000
|
|
34
34
|
#define FlippedAddressMask (AddressMask^0xffffffff)
|
|
35
|
-
// the address of the black hole, getVirtualMemAddress(2);
|
|
36
|
-
#define
|
|
35
|
+
// the address of InvalidMem(the black hole), getVirtualMemAddress(2);
|
|
36
|
+
#define InvalidMemAddr 0x7f000000 + 2
|
|
37
|
+
// the address of NullMem, getVirtualMemAddress(0);
|
|
38
|
+
#define NullMemAddr 0x7f000000
|
|
39
|
+
|
|
40
|
+
|
|
37
41
|
|
|
38
42
|
#include "Util/GeneralType.h"
|
|
39
43
|
#include <sstream>
|
|
@@ -42,10 +46,19 @@ namespace SVF
|
|
|
42
46
|
{
|
|
43
47
|
class AddressValue
|
|
44
48
|
{
|
|
49
|
+
friend class AbstractState;
|
|
50
|
+
friend class RelExeState;
|
|
45
51
|
public:
|
|
46
52
|
typedef Set<u32_t> AddrSet;
|
|
47
53
|
private:
|
|
48
54
|
AddrSet _addrs;
|
|
55
|
+
|
|
56
|
+
/// Return the internal index if idx is an address otherwise return the value of idx
|
|
57
|
+
static inline u32_t getInternalID(u32_t idx)
|
|
58
|
+
{
|
|
59
|
+
return (idx & FlippedAddressMask);
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
public:
|
|
50
63
|
/// Default constructor
|
|
51
64
|
AddressValue() {}
|
|
@@ -168,26 +181,11 @@ public:
|
|
|
168
181
|
return !v.empty();
|
|
169
182
|
}
|
|
170
183
|
|
|
171
|
-
inline bool isTop() const
|
|
172
|
-
{
|
|
173
|
-
return *this->begin() == BlackHoleAddr;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
184
|
inline bool isBottom() const
|
|
177
185
|
{
|
|
178
186
|
return empty();
|
|
179
187
|
}
|
|
180
188
|
|
|
181
|
-
inline void setTop()
|
|
182
|
-
{
|
|
183
|
-
*this = AddressValue(BlackHoleAddr);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
inline void setBottom()
|
|
187
|
-
{
|
|
188
|
-
_addrs.clear();
|
|
189
|
-
}
|
|
190
|
-
|
|
191
189
|
const std::string toString() const
|
|
192
190
|
{
|
|
193
191
|
std::string str;
|
|
@@ -222,11 +220,6 @@ public:
|
|
|
222
220
|
return (val & 0xff000000) == AddressMask && val != AddressMask + 0;
|
|
223
221
|
}
|
|
224
222
|
|
|
225
|
-
/// Return the internal index if idx is an address otherwise return the value of idx
|
|
226
|
-
static inline u32_t getInternalID(u32_t idx)
|
|
227
|
-
{
|
|
228
|
-
return (idx & FlippedAddressMask);
|
|
229
|
-
}
|
|
230
223
|
};
|
|
231
224
|
} // end namespace SVF
|
|
232
225
|
#endif //Z3_EXAMPLE_ADDRESSVALUE_H
|
|
@@ -45,6 +45,7 @@ public:
|
|
|
45
45
|
enum DetectorKind
|
|
46
46
|
{
|
|
47
47
|
BUF_OVERFLOW, ///< Detector for buffer overflow issues.
|
|
48
|
+
NULL_DEREF, ///< Detector for nullptr dereference issues.
|
|
48
49
|
UNKNOWN, ///< Default type if the kind is not specified.
|
|
49
50
|
};
|
|
50
51
|
|
|
@@ -164,7 +165,8 @@ public:
|
|
|
164
165
|
* @param objAddrs Address value for the object.
|
|
165
166
|
* @param offset The interval value of the offset.
|
|
166
167
|
*/
|
|
167
|
-
void updateGepObjOffsetFromBase(
|
|
168
|
+
void updateGepObjOffsetFromBase(AbstractState& as,
|
|
169
|
+
AddressValue gepAddrs,
|
|
168
170
|
AddressValue objAddrs,
|
|
169
171
|
IntervalValue offset);
|
|
170
172
|
|
|
@@ -320,4 +322,115 @@ private:
|
|
|
320
322
|
SVFBugReport recoder; ///< Recorder for abstract execution bugs.
|
|
321
323
|
Map<const ICFGNode*, std::string> nodeToBugInfo; ///< Maps ICFG nodes to bug information.
|
|
322
324
|
};
|
|
325
|
+
class NullptrDerefDetector : public AEDetector{
|
|
326
|
+
friend class AbstractInterpretation;
|
|
327
|
+
public:
|
|
328
|
+
NullptrDerefDetector()
|
|
329
|
+
{
|
|
330
|
+
kind = NULL_DEREF;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
~NullptrDerefDetector() = default;
|
|
334
|
+
|
|
335
|
+
static bool classof(const AEDetector* detector)
|
|
336
|
+
{
|
|
337
|
+
return detector->getKind() == AEDetector::NULL_DEREF;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* @brief Detects nullptr dereferences issues within a node.
|
|
342
|
+
* @param as Reference to the abstract state.
|
|
343
|
+
* @param node Pointer to the ICFG node.
|
|
344
|
+
*/
|
|
345
|
+
void detect(AbstractState& as, const ICFGNode* node);
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @brief Handles external API calls related to nullptr dereferences.
|
|
349
|
+
* @param call Pointer to the call ICFG node.
|
|
350
|
+
*/
|
|
351
|
+
void handleStubFunctions(const CallICFGNode* call);
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @brief Checks if an Abstract Value is uninitialized.
|
|
355
|
+
* @param v The Abstract Value to check.
|
|
356
|
+
* @return True if the value is uninitialized, false otherwise.
|
|
357
|
+
*/
|
|
358
|
+
bool isUninit(AbstractValue v)
|
|
359
|
+
{
|
|
360
|
+
bool is = v.getAddrs().isBottom() && v.getInterval().isBottom();
|
|
361
|
+
return is;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* @brief Adds a bug to the reporter based on an exception.
|
|
366
|
+
* @param e The exception that was thrown.
|
|
367
|
+
* @param node Pointer to the ICFG node where the bug was detected.
|
|
368
|
+
*/
|
|
369
|
+
void addBugToReporter(const AEException& e, const ICFGNode* node)
|
|
370
|
+
{
|
|
371
|
+
GenericBug::EventStack eventStack;
|
|
372
|
+
SVFBugEvent sourceInstEvent(SVFBugEvent::EventType::SourceInst, node);
|
|
373
|
+
eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
|
|
374
|
+
|
|
375
|
+
if (eventStack.empty())
|
|
376
|
+
{
|
|
377
|
+
return; // If the event stack is empty, return early
|
|
378
|
+
}
|
|
379
|
+
std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
|
|
380
|
+
|
|
381
|
+
// Check if the bug at this location has already been reported
|
|
382
|
+
if (bugLoc.find(loc) != bugLoc.end())
|
|
383
|
+
{
|
|
384
|
+
return; // If the bug location is already reported, return early
|
|
385
|
+
}
|
|
386
|
+
else
|
|
387
|
+
{
|
|
388
|
+
bugLoc.insert(loc); // Otherwise, mark this location as reported
|
|
389
|
+
}
|
|
390
|
+
recoder.addAbsExecBug(GenericBug::FULLNULLPTRDEREFERENCE, eventStack, 0, 0, 0, 0);
|
|
391
|
+
nodeToBugInfo[node] = e.what(); // Record the exception information for the node
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @brief Reports all detected nullptr dereference bugs.
|
|
396
|
+
*/
|
|
397
|
+
void reportBug()
|
|
398
|
+
{
|
|
399
|
+
if (!nodeToBugInfo.empty())
|
|
400
|
+
{
|
|
401
|
+
std::cerr << "###################### Nullptr Dereference (" + std::to_string(nodeToBugInfo.size())
|
|
402
|
+
+ " found)######################\n";
|
|
403
|
+
std::cerr << "---------------------------------------------\n";
|
|
404
|
+
for (const auto& it : nodeToBugInfo)
|
|
405
|
+
{
|
|
406
|
+
std::cerr << it.second << "\n---------------------------------------------\n";
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* @brief Handle external API calls related to nullptr dereferences.
|
|
413
|
+
* @param as Reference to the abstract state.
|
|
414
|
+
* @param call Pointer to the call ICFG node.
|
|
415
|
+
*/
|
|
416
|
+
void detectExtAPI(AbstractState& as, const CallICFGNode* call);
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* @brief Check if an Abstract Value is NULL (or uninitialized).
|
|
421
|
+
*
|
|
422
|
+
* @param v An Abstract Value of loaded from an address in an Abstract State.
|
|
423
|
+
*/
|
|
424
|
+
bool isNull(AbstractValue v)
|
|
425
|
+
{
|
|
426
|
+
return !v.isAddr() && !v.isInterval();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
bool canSafelyDerefPtr(AbstractState& as, const SVFVar* ptr);
|
|
430
|
+
|
|
431
|
+
private:
|
|
432
|
+
Set<std::string> bugLoc; ///< Set of locations where bugs have been reported.
|
|
433
|
+
SVFBugReport recoder; ///< Recorder for abstract execution bugs.
|
|
434
|
+
Map<const ICFGNode*, std::string> nodeToBugInfo; ///< Maps ICFG nodes to bug information.
|
|
435
|
+
};
|
|
323
436
|
}
|
|
@@ -105,6 +105,7 @@ class AbstractInterpretation
|
|
|
105
105
|
friend class AEStat;
|
|
106
106
|
friend class AEAPI;
|
|
107
107
|
friend class BufOverflowDetector;
|
|
108
|
+
friend class NullptrDerefDetector;
|
|
108
109
|
|
|
109
110
|
public:
|
|
110
111
|
typedef SCCDetection<CallGraph*> CallGraphSCC;
|
|
@@ -155,6 +156,25 @@ public:
|
|
|
155
156
|
|
|
156
157
|
Set<const CallICFGNode*> checkpoints; // for CI check
|
|
157
158
|
|
|
159
|
+
/**
|
|
160
|
+
* @brief Retrieves the abstract state from the trace for a given ICFG node.
|
|
161
|
+
* @param node Pointer to the ICFG node.
|
|
162
|
+
* @return Reference to the abstract state.
|
|
163
|
+
* @throws Assertion if no trace exists for the node.
|
|
164
|
+
*/
|
|
165
|
+
AbstractState& getAbsStateFromTrace(const ICFGNode* node)
|
|
166
|
+
{
|
|
167
|
+
const ICFGNode* repNode = icfg->getRepNode(node);
|
|
168
|
+
if (abstractTrace.count(repNode) == 0)
|
|
169
|
+
{
|
|
170
|
+
assert(false && "No preAbsTrace for this node");
|
|
171
|
+
}
|
|
172
|
+
else
|
|
173
|
+
{
|
|
174
|
+
return abstractTrace[repNode];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
158
178
|
private:
|
|
159
179
|
/// Global ICFGNode is handled at the entry of the program,
|
|
160
180
|
virtual void handleGlobalNode();
|
|
@@ -280,19 +300,6 @@ private:
|
|
|
280
300
|
Set<const FunObjVar*> recursiveFuns;
|
|
281
301
|
|
|
282
302
|
|
|
283
|
-
AbstractState& getAbsStateFromTrace(const ICFGNode* node)
|
|
284
|
-
{
|
|
285
|
-
const ICFGNode* repNode = icfg->getRepNode(node);
|
|
286
|
-
if (abstractTrace.count(repNode) == 0)
|
|
287
|
-
{
|
|
288
|
-
assert(0 && "No preAbsTrace for this node");
|
|
289
|
-
}
|
|
290
|
-
else
|
|
291
|
-
{
|
|
292
|
-
return abstractTrace[repNode];
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
303
|
bool hasAbsStateFromTrace(const ICFGNode* node)
|
|
297
304
|
{
|
|
298
305
|
const ICFGNode* repNode = icfg->getRepNode(node);
|
|
@@ -253,6 +253,8 @@ public:
|
|
|
253
253
|
static const Option<std::string> OutputName;
|
|
254
254
|
/// buffer overflow checker, Default: false
|
|
255
255
|
static const Option<bool> BufferOverflowCheck;
|
|
256
|
+
/// nullptr dereference checker, Default: false
|
|
257
|
+
static const Option<bool> NullDerefCheck;
|
|
256
258
|
/// memory leak check, Default: false
|
|
257
259
|
static const Option<bool> MemoryLeakCheck;
|
|
258
260
|
/// file open close checker, Default: false
|
|
@@ -127,6 +127,7 @@ void AbstractState::joinWith(const AbstractState& other)
|
|
|
127
127
|
_addrToAbsVal.emplace(key, it->second);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
_freedAddrs.insert(other._freedAddrs.begin(), other._freedAddrs.end());
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
/// domain meet with other, important! other widen this.
|
|
@@ -150,6 +151,11 @@ void AbstractState::meetWith(const AbstractState& other)
|
|
|
150
151
|
oit->second.meet_with(it->second);
|
|
151
152
|
}
|
|
152
153
|
}
|
|
154
|
+
Set<NodeID> intersection;
|
|
155
|
+
std::set_intersection(_freedAddrs.begin(), _freedAddrs.end(),
|
|
156
|
+
other._freedAddrs.begin(), other._freedAddrs.end(),
|
|
157
|
+
std::inserter(intersection, intersection.begin()));
|
|
158
|
+
_freedAddrs = std::move(intersection);
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
// getGepObjAddrs
|
|
@@ -165,7 +171,7 @@ AddressValue AbstractState::getGepObjAddrs(u32_t pointer, IntervalValue offset)
|
|
|
165
171
|
AbstractValue addrs = (*this)[pointer];
|
|
166
172
|
for (const auto& addr : addrs.getAddrs())
|
|
167
173
|
{
|
|
168
|
-
s64_t baseObj =
|
|
174
|
+
s64_t baseObj = getIDFromAddr(addr);
|
|
169
175
|
assert(SVFUtil::isa<ObjVar>(PAG::getPAG()->getGNode(baseObj)) && "Fail to get the base object address!");
|
|
170
176
|
NodeID gepObj = PAG::getPAG()->getGepObjVar(baseObj, i);
|
|
171
177
|
(*this)[gepObj] = AddressValue(AbstractState::getVirtualMemAddress(gepObj));
|
|
@@ -470,7 +476,7 @@ const SVFType* AbstractState::getPointeeElement(NodeID id)
|
|
|
470
476
|
const AbstractValue& addrs = (*this)[id];
|
|
471
477
|
for (auto addr: addrs.getAddrs())
|
|
472
478
|
{
|
|
473
|
-
NodeID addr_id =
|
|
479
|
+
NodeID addr_id = getIDFromAddr(addr);
|
|
474
480
|
if (addr_id == 0) // nullptr skip
|
|
475
481
|
continue;
|
|
476
482
|
return svfir->getBaseObject(addr_id)->getType();
|