svf-tools 1.0.1020 → 1.0.1022
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/build.sh +4 -4
- package/package.json +1 -1
- package/svf/include/Graphs/CFLGraph.h +0 -1
- package/svf/include/Util/ExtAPI.h +3 -0
- package/svf/lib/CFL/CFGNormalizer.cpp +15 -5
- package/svf/lib/CFL/CFLGraphBuilder.cpp +55 -26
- package/svf/lib/CFL/GrammarBuilder.cpp +72 -27
- package/svf/lib/Util/ExtAPI.cpp +10 -5
- package/svf-llvm/include/SVF-LLVM/LLVMUtil.h +10 -0
- package/svf-llvm/lib/LLVMUtil.cpp +35 -0
- package/svf-llvm/lib/SVFIRBuilder.cpp +1 -1
- package/svf-llvm/lib/SymbolTableBuilder.cpp +3 -3
- package/svf-llvm/lib/extapi.c +176 -136
package/build.sh
CHANGED
|
@@ -250,10 +250,10 @@ BUILD_DIR="./${BUILD_TYPE}-build"
|
|
|
250
250
|
rm -rf "${BUILD_DIR}"
|
|
251
251
|
mkdir "${BUILD_DIR}"
|
|
252
252
|
# If you need shared libs, turn BUILD_SHARED_LIBS on
|
|
253
|
-
cmake -D CMAKE_BUILD_TYPE:STRING="${BUILD_TYPE}"
|
|
254
|
-
-DSVF_ENABLE_ASSERTIONS:BOOL=true
|
|
255
|
-
-DSVF_SANITIZE="${SVF_SANITIZER}"
|
|
256
|
-
-DBUILD_SHARED_LIBS=off
|
|
253
|
+
cmake -D CMAKE_BUILD_TYPE:STRING="${BUILD_TYPE}" \
|
|
254
|
+
-DSVF_ENABLE_ASSERTIONS:BOOL=true \
|
|
255
|
+
-DSVF_SANITIZE="${SVF_SANITIZER}" \
|
|
256
|
+
-DBUILD_SHARED_LIBS=off \
|
|
257
257
|
-S "${SVFHOME}" -B "${BUILD_DIR}"
|
|
258
258
|
cmake --build "${BUILD_DIR}" -j ${jobs}
|
|
259
259
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1022",
|
|
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": {
|
|
@@ -91,6 +91,9 @@ public:
|
|
|
91
91
|
// Does (F) allocate a new object and assign it to one of its arguments?
|
|
92
92
|
bool is_arg_alloc(const SVFFunction *F);
|
|
93
93
|
|
|
94
|
+
// Does (F) allocate a new stack object and return it?
|
|
95
|
+
bool is_alloc_stack_ret(const SVFFunction *F);
|
|
96
|
+
|
|
94
97
|
// Get the position of argument which holds the new object
|
|
95
98
|
s32_t get_alloc_arg_pos(const SVFFunction *F);
|
|
96
99
|
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
#include "Util/WorkList.h"
|
|
33
33
|
#include "SVFIR/SVFValue.h"
|
|
34
34
|
#include <string>
|
|
35
|
-
#include <regex>
|
|
36
35
|
#include <fstream>
|
|
37
36
|
#include <sstream>
|
|
38
37
|
#include <iostream>
|
|
@@ -437,13 +436,23 @@ void CFGNormalizer::ebnfSignReplace(char sign, CFGrammar *grammar)
|
|
|
437
436
|
|
|
438
437
|
void CFGNormalizer::strTrans(std::string LHS, CFGrammar *grammar, GrammarBase::Production& normalProd)
|
|
439
438
|
{
|
|
440
|
-
|
|
441
|
-
|
|
439
|
+
// Find the position of the first non-whitespace character
|
|
440
|
+
size_t start = LHS.find_first_not_of(" \t\n\r");
|
|
441
|
+
// If the string contains non-whitespace characters, remove leading spaces
|
|
442
|
+
if (start != std::string::npos)
|
|
443
|
+
{
|
|
444
|
+
LHS = LHS.substr(start);
|
|
445
|
+
}
|
|
446
|
+
else
|
|
447
|
+
{
|
|
448
|
+
// If the string contains only spaces, clear it
|
|
449
|
+
LHS.clear();
|
|
450
|
+
}
|
|
451
|
+
|
|
442
452
|
std::string delimiter;
|
|
443
453
|
size_t pos;
|
|
444
454
|
std::string word;
|
|
445
|
-
|
|
446
|
-
LHS = matches.str(1);
|
|
455
|
+
|
|
447
456
|
delimiter = " ";
|
|
448
457
|
while ((pos = LHS.find(delimiter)) != std::string::npos)
|
|
449
458
|
{
|
|
@@ -454,6 +463,7 @@ void CFGNormalizer::strTrans(std::string LHS, CFGrammar *grammar, GrammarBase::P
|
|
|
454
463
|
normalProd.push_back(grammar->strToSymbol(LHS));
|
|
455
464
|
}
|
|
456
465
|
|
|
466
|
+
|
|
457
467
|
GrammarBase::Symbol CFGNormalizer::check_head(GrammarBase::SymbolMap<GrammarBase::Symbol, GrammarBase::Productions> &grammar, GrammarBase::Production &rule)
|
|
458
468
|
{
|
|
459
469
|
for(auto symProdPair: grammar)
|
|
@@ -193,49 +193,79 @@ CFLGraph* CFLGraphBuilder::buildFromText(std::string fileName, GrammarBase *gram
|
|
|
193
193
|
return cflGraph;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
CFLGraph *
|
|
196
|
+
CFLGraph *CFLGraphBuilder::buildFromDot(std::string fileName, GrammarBase *grammar, BuildDirection direction)
|
|
197
197
|
{
|
|
198
198
|
buildlabelToKindMap(grammar);
|
|
199
199
|
cflGraph = new CFLGraph(grammar->getStartKind());
|
|
200
200
|
std::string lineString;
|
|
201
201
|
std::ifstream inputFile(fileName);
|
|
202
202
|
std::cout << "Building CFL Graph from dot file: " << fileName << "..\n";
|
|
203
|
-
std::regex reg("Node(\\w+)\\s*->\\s*Node(\\w+)\\s*\\[.*label=(.*)\\]");
|
|
204
203
|
std::cout << std::boolalpha;
|
|
205
|
-
|
|
204
|
+
|
|
205
|
+
u32_t lineNum = 0;
|
|
206
206
|
current = labelToKindMap.size();
|
|
207
207
|
|
|
208
208
|
while (getline(inputFile, lineString))
|
|
209
209
|
{
|
|
210
210
|
lineNum += 1;
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
|
|
212
|
+
// Find "Node" prefixes and "->"
|
|
213
|
+
size_t srcStart = lineString.find("Node");
|
|
214
|
+
if (srcStart == std::string::npos) continue;
|
|
215
|
+
|
|
216
|
+
size_t srcEnd = lineString.find(" ", srcStart);
|
|
217
|
+
if (srcEnd == std::string::npos) continue;
|
|
218
|
+
|
|
219
|
+
size_t arrowPos = lineString.find("->", srcEnd);
|
|
220
|
+
if (arrowPos == std::string::npos) continue;
|
|
221
|
+
|
|
222
|
+
size_t dstStart = lineString.find("Node", arrowPos);
|
|
223
|
+
if (dstStart == std::string::npos) continue;
|
|
224
|
+
|
|
225
|
+
size_t dstEnd = lineString.find(" ", dstStart);
|
|
226
|
+
if (dstEnd == std::string::npos) continue;
|
|
227
|
+
|
|
228
|
+
size_t labelStart = lineString.find("label=", dstEnd);
|
|
229
|
+
if (labelStart == std::string::npos) continue;
|
|
230
|
+
|
|
231
|
+
labelStart += 6; // Move past "label=" to the start of the label
|
|
232
|
+
size_t labelEnd = lineString.find_first_of("]", labelStart);
|
|
233
|
+
if (labelEnd == std::string::npos) continue;
|
|
234
|
+
|
|
235
|
+
// Extract the source ID, destination ID, and label
|
|
236
|
+
std::string srcIDStr = lineString.substr(srcStart + 4, srcEnd - (srcStart + 4));
|
|
237
|
+
std::string dstIDStr = lineString.substr(dstStart + 4, dstEnd - (dstStart + 4));
|
|
238
|
+
std::string label = lineString.substr(labelStart, labelEnd - labelStart);
|
|
239
|
+
|
|
240
|
+
// Convert source and destination IDs from hexadecimal
|
|
241
|
+
u32_t srcID = std::stoul(srcIDStr, nullptr, 16);
|
|
242
|
+
u32_t dstID = std::stoul(dstIDStr, nullptr, 16);
|
|
243
|
+
|
|
244
|
+
CFLNode *src = addGNode(srcID);
|
|
245
|
+
CFLNode *dst = addGNode(dstID);
|
|
246
|
+
|
|
247
|
+
if (labelToKindMap.find(label) != labelToKindMap.end())
|
|
248
|
+
{
|
|
249
|
+
cflGraph->addCFLEdge(src, dst, labelToKindMap[label]);
|
|
250
|
+
}
|
|
251
|
+
else
|
|
213
252
|
{
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
CFLNode *src = addGNode(srcID);
|
|
218
|
-
CFLNode *dst = addGNode(dstID);
|
|
219
|
-
if (labelToKindMap.find(label) != labelToKindMap.end())
|
|
253
|
+
if (Options::FlexSymMap() == true)
|
|
254
|
+
{
|
|
255
|
+
labelToKindMap.insert({label, current++});
|
|
220
256
|
cflGraph->addCFLEdge(src, dst, labelToKindMap[label]);
|
|
257
|
+
}
|
|
221
258
|
else
|
|
222
259
|
{
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
else
|
|
229
|
-
{
|
|
230
|
-
std::string msg = "In line " + std::to_string(lineNum) +
|
|
231
|
-
" sym can not find in grammar, please correct the input dot or set --flexsymmap.";
|
|
232
|
-
SVFUtil::errMsg(msg);
|
|
233
|
-
std::cout << msg;
|
|
234
|
-
abort();
|
|
235
|
-
}
|
|
260
|
+
std::string msg = "In line " + std::to_string(lineNum) +
|
|
261
|
+
" sym cannot be found in grammar. Please correct the input dot or set --flexsymmap.";
|
|
262
|
+
SVFUtil::errMsg(msg);
|
|
263
|
+
std::cout << msg;
|
|
264
|
+
abort();
|
|
236
265
|
}
|
|
237
266
|
}
|
|
238
267
|
}
|
|
268
|
+
|
|
239
269
|
inputFile.close();
|
|
240
270
|
return cflGraph;
|
|
241
271
|
}
|
|
@@ -247,7 +277,6 @@ CFLGraph* CFLGraphBuilder::buildFromJson(std::string fileName, GrammarBase *gram
|
|
|
247
277
|
return cflGraph;
|
|
248
278
|
}
|
|
249
279
|
|
|
250
|
-
|
|
251
280
|
CFLGraph* AliasCFLGraphBuilder::buildBigraph(ConstraintGraph *graph, Kind startKind, GrammarBase *grammar)
|
|
252
281
|
{
|
|
253
282
|
cflGraph = new CFLGraph(startKind);
|
|
@@ -543,4 +572,4 @@ CFLGraph* VFCFLGraphBuilder::buildBiPEGgraph(ConstraintGraph *graph, Kind startK
|
|
|
543
572
|
}
|
|
544
573
|
|
|
545
574
|
|
|
546
|
-
} // end of SVF namespace
|
|
575
|
+
} // end of SVF namespace
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
|
|
30
30
|
#include <string>
|
|
31
31
|
#include <fstream>
|
|
32
|
-
#include <regex>
|
|
33
32
|
#include <sstream>
|
|
34
33
|
#include <iostream>
|
|
35
34
|
#include "CFL/GrammarBuilder.h"
|
|
@@ -44,48 +43,69 @@ const inline std::string GrammarBuilder::parseProductionsString() const
|
|
|
44
43
|
std::cerr << "Can't open CFL grammar file `" << fileName << "`" << std::endl;
|
|
45
44
|
abort();
|
|
46
45
|
}
|
|
46
|
+
|
|
47
47
|
std::string lineString;
|
|
48
48
|
std::string lines = "";
|
|
49
49
|
std::string startString;
|
|
50
50
|
std::string symbolString;
|
|
51
51
|
const std::string WHITESPACE = " \n\r\t\f\v";
|
|
52
52
|
int lineNum = 0;
|
|
53
|
+
|
|
53
54
|
while (getline(textFile, lineString))
|
|
54
55
|
{
|
|
55
|
-
if(lineNum == 1)
|
|
56
|
+
if (lineNum == 1)
|
|
56
57
|
{
|
|
57
58
|
startString = stripSpace(lineString);
|
|
58
59
|
}
|
|
59
|
-
if(lineNum == 3)
|
|
60
|
+
else if (lineNum == 3)
|
|
61
|
+
{
|
|
62
|
+
// Trim leading and trailing whitespace
|
|
63
|
+
size_t start = lineString.find_first_not_of(WHITESPACE);
|
|
64
|
+
size_t end = lineString.find_last_not_of(WHITESPACE);
|
|
65
|
+
if (start != std::string::npos && end != std::string::npos)
|
|
66
|
+
{
|
|
67
|
+
symbolString = lineString.substr(start, end - start + 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Append line to `lines` with whitespace trimmed
|
|
72
|
+
size_t start = lineString.find_first_not_of(WHITESPACE);
|
|
73
|
+
size_t end = lineString.find_last_not_of(WHITESPACE);
|
|
74
|
+
if (start != std::string::npos && end != std::string::npos)
|
|
60
75
|
{
|
|
61
|
-
|
|
76
|
+
lines.append(lineString.substr(start, end - start + 1));
|
|
62
77
|
}
|
|
63
78
|
|
|
64
|
-
lines.append(lineString.substr(lineString.find_first_not_of(WHITESPACE), lineString.find_last_not_of(WHITESPACE)+1));
|
|
65
79
|
lineNum++;
|
|
66
80
|
}
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (std::
|
|
82
|
+
// Extract "Productions:" part from `lines` manually
|
|
83
|
+
size_t productionsPos = lines.find("Productions:");
|
|
84
|
+
if (productionsPos != std::string::npos)
|
|
71
85
|
{
|
|
72
|
-
lines =
|
|
86
|
+
lines = lines.substr(productionsPos + std::string("Productions:").length());
|
|
73
87
|
}
|
|
88
|
+
|
|
89
|
+
// Parse `symbolString` to insert symbols
|
|
74
90
|
std::string sString;
|
|
75
91
|
size_t pos = 0;
|
|
76
92
|
while ((pos = symbolString.find(" ")) != std::string::npos)
|
|
77
93
|
{
|
|
78
94
|
sString = stripSpace(symbolString.substr(0, pos));
|
|
79
|
-
symbolString.erase(0, pos + 1); //
|
|
95
|
+
symbolString.erase(0, pos + 1); // Remove the processed part
|
|
80
96
|
grammar->insertSymbol(sString);
|
|
81
97
|
}
|
|
98
|
+
// Insert the remaining symbol
|
|
82
99
|
grammar->insertSymbol(symbolString);
|
|
100
|
+
|
|
101
|
+
// Set the start kind and add the epsilon terminal
|
|
83
102
|
grammar->setStartKind(grammar->insertSymbol(startString));
|
|
84
103
|
grammar->insertTerminalKind("epsilon");
|
|
85
104
|
|
|
86
105
|
return lines;
|
|
87
106
|
}
|
|
88
107
|
|
|
108
|
+
|
|
89
109
|
const inline std::vector<std::string> GrammarBuilder::loadWordProductions() const
|
|
90
110
|
{
|
|
91
111
|
size_t pos = 0;
|
|
@@ -104,17 +124,21 @@ const inline std::vector<std::string> GrammarBuilder::loadWordProductions() cons
|
|
|
104
124
|
|
|
105
125
|
const inline std::string GrammarBuilder::stripSpace(std::string s) const
|
|
106
126
|
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
// Remove leading spaces
|
|
128
|
+
size_t start = s.find_first_not_of(" ");
|
|
129
|
+
if (start == std::string::npos)
|
|
130
|
+
{
|
|
131
|
+
return ""; // Return an empty string if no non-space character is found
|
|
132
|
+
}
|
|
112
133
|
|
|
134
|
+
// Remove trailing spaces
|
|
135
|
+
size_t end = s.find_last_not_of(" ");
|
|
136
|
+
return s.substr(start, end - start + 1);
|
|
137
|
+
}
|
|
113
138
|
|
|
114
|
-
///
|
|
139
|
+
/// Build grammarbase from textfile
|
|
115
140
|
GrammarBase* GrammarBuilder::build() const
|
|
116
141
|
{
|
|
117
|
-
std::smatch matches;
|
|
118
142
|
std::string delimiter = " ";
|
|
119
143
|
std::string delimiter1 = "->";
|
|
120
144
|
std::string word = "";
|
|
@@ -124,29 +148,50 @@ GrammarBase* GrammarBuilder::build() const
|
|
|
124
148
|
|
|
125
149
|
for (auto wordProd : wordProdVec)
|
|
126
150
|
{
|
|
151
|
+
// Find the position of the '->' delimiter
|
|
127
152
|
if ((pos = wordProd.find(delimiter1)) != std::string::npos)
|
|
128
153
|
{
|
|
154
|
+
// Extract and strip RHS (right-hand side) and LHS (left-hand side)
|
|
129
155
|
std::string RHS = stripSpace(wordProd.substr(0, pos));
|
|
130
|
-
std::string LHS = wordProd.substr(pos + delimiter1.size()
|
|
156
|
+
std::string LHS = stripSpace(wordProd.substr(pos + delimiter1.size()));
|
|
157
|
+
|
|
158
|
+
// Insert RHS symbol into grammar
|
|
131
159
|
GrammarBase::Symbol RHSSymbol = grammar->insertSymbol(RHS);
|
|
132
160
|
prod.push_back(RHSSymbol);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
161
|
+
|
|
162
|
+
// Ensure RHS symbol exists in raw productions
|
|
163
|
+
if (grammar->getRawProductions().find(RHSSymbol) == grammar->getRawProductions().end())
|
|
164
|
+
{
|
|
165
|
+
grammar->getRawProductions().insert({RHSSymbol, {}});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Parse LHS string into symbols
|
|
137
169
|
while ((pos = LHS.find(delimiter)) != std::string::npos)
|
|
138
170
|
{
|
|
139
|
-
word
|
|
140
|
-
LHS.
|
|
171
|
+
// Extract each word before the space
|
|
172
|
+
word = stripSpace(LHS.substr(0, pos));
|
|
173
|
+
LHS.erase(0, pos + delimiter.length());
|
|
174
|
+
|
|
175
|
+
// Insert symbol into production
|
|
141
176
|
prod.push_back(grammar->insertSymbol(word));
|
|
142
177
|
}
|
|
143
|
-
|
|
178
|
+
|
|
179
|
+
// Insert the remaining word (if any) into the production
|
|
180
|
+
if (!LHS.empty())
|
|
181
|
+
{
|
|
182
|
+
prod.push_back(grammar->insertSymbol(stripSpace(LHS)));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Add the production to raw productions
|
|
144
186
|
grammar->getRawProductions().at(RHSSymbol).insert(prod);
|
|
187
|
+
|
|
188
|
+
// Clear the production for the next iteration
|
|
145
189
|
prod = {};
|
|
146
190
|
}
|
|
147
191
|
}
|
|
148
192
|
|
|
149
193
|
return grammar;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
194
|
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
}
|
package/svf/lib/Util/ExtAPI.cpp
CHANGED
|
@@ -216,19 +216,24 @@ bool ExtAPI::is_memset(const SVFFunction *F)
|
|
|
216
216
|
|
|
217
217
|
bool ExtAPI::is_alloc(const SVFFunction* F)
|
|
218
218
|
{
|
|
219
|
-
return F && hasExtFuncAnnotation(F, "
|
|
219
|
+
return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_RET");
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
// Does (F) allocate a new object and assign it to one of its arguments?
|
|
223
223
|
bool ExtAPI::is_arg_alloc(const SVFFunction* F)
|
|
224
224
|
{
|
|
225
|
-
return F && hasExtFuncAnnotation(F, "
|
|
225
|
+
return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
bool ExtAPI::is_alloc_stack_ret(const SVFFunction* F)
|
|
229
|
+
{
|
|
230
|
+
return F && hasExtFuncAnnotation(F, "ALLOC_STACK_RET");
|
|
226
231
|
}
|
|
227
232
|
|
|
228
233
|
// Get the position of argument which holds the new object
|
|
229
234
|
s32_t ExtAPI::get_alloc_arg_pos(const SVFFunction* F)
|
|
230
235
|
{
|
|
231
|
-
std::string allocArg = getExtFuncAnnotation(F, "
|
|
236
|
+
std::string allocArg = getExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
|
|
232
237
|
assert(!allocArg.empty() && "Not an alloc call via argument or incorrect extern function annotation!");
|
|
233
238
|
|
|
234
239
|
std::string number;
|
|
@@ -237,14 +242,14 @@ s32_t ExtAPI::get_alloc_arg_pos(const SVFFunction* F)
|
|
|
237
242
|
if (isdigit(c))
|
|
238
243
|
number.push_back(c);
|
|
239
244
|
}
|
|
240
|
-
assert(!number.empty() && "Incorrect naming convention for svf external functions(
|
|
245
|
+
assert(!number.empty() && "Incorrect naming convention for svf external functions(ALLOC_HEAP_ARG + number)?");
|
|
241
246
|
return std::stoi(number);
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
// Does (F) reallocate a new object?
|
|
245
250
|
bool ExtAPI::is_realloc(const SVFFunction* F)
|
|
246
251
|
{
|
|
247
|
-
return F && hasExtFuncAnnotation(F, "
|
|
252
|
+
return F && hasExtFuncAnnotation(F, "REALLOC_HEAP_RET");
|
|
248
253
|
}
|
|
249
254
|
|
|
250
255
|
|
|
@@ -360,9 +360,19 @@ inline bool isHeapAllocExtCall(const Instruction *inst)
|
|
|
360
360
|
return isHeapAllocExtCallViaRet(inst) || isHeapAllocExtCallViaArg(inst);
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
bool isStackAllocExtCallViaRet(const Instruction *inst);
|
|
364
|
+
|
|
365
|
+
inline bool isStackAllocExtCall(const Instruction *inst)
|
|
366
|
+
{
|
|
367
|
+
return isStackAllocExtCallViaRet(inst);
|
|
368
|
+
}
|
|
369
|
+
|
|
363
370
|
// Check if a given value represents a heap object.
|
|
364
371
|
bool isHeapObj(const Value* val);
|
|
365
372
|
|
|
373
|
+
// Check if a given value represents a stack object.
|
|
374
|
+
bool isStackObj(const Value* val);
|
|
375
|
+
|
|
366
376
|
/// Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls
|
|
367
377
|
bool isNonInstricCallSite(const Instruction* inst);
|
|
368
378
|
|
|
@@ -646,6 +646,21 @@ bool LLVMUtil::isHeapAllocExtCallViaArg(const Instruction* inst)
|
|
|
646
646
|
}
|
|
647
647
|
}
|
|
648
648
|
|
|
649
|
+
bool LLVMUtil::isStackAllocExtCallViaRet(const Instruction *inst)
|
|
650
|
+
{
|
|
651
|
+
LLVMModuleSet* pSet = LLVMModuleSet::getLLVMModuleSet();
|
|
652
|
+
ExtAPI* extApi = ExtAPI::getExtAPI();
|
|
653
|
+
bool isPtrTy = inst->getType()->isPointerTy();
|
|
654
|
+
if (const CallBase* call = SVFUtil::dyn_cast<CallBase>(inst))
|
|
655
|
+
{
|
|
656
|
+
const Function* fun = call->getCalledFunction();
|
|
657
|
+
return fun && isPtrTy &&
|
|
658
|
+
extApi->is_alloc_stack_ret(pSet->getSVFFunction(fun));
|
|
659
|
+
}
|
|
660
|
+
else
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
|
|
649
664
|
/**
|
|
650
665
|
* Check if a given value represents a heap object.
|
|
651
666
|
*
|
|
@@ -670,6 +685,26 @@ bool LLVMUtil::isHeapObj(const Value* val)
|
|
|
670
685
|
return false;
|
|
671
686
|
}
|
|
672
687
|
|
|
688
|
+
/**
|
|
689
|
+
* @param val The value to check.
|
|
690
|
+
* @return True if the value represents a stack object, false otherwise.
|
|
691
|
+
*/
|
|
692
|
+
bool LLVMUtil::isStackObj(const Value* val)
|
|
693
|
+
{
|
|
694
|
+
if (SVFUtil::isa<AllocaInst>(val))
|
|
695
|
+
{
|
|
696
|
+
return true;
|
|
697
|
+
}
|
|
698
|
+
// Check if the value is an instruction and if it is a stack allocation external call
|
|
699
|
+
else if (SVFUtil::isa<Instruction>(val) &&
|
|
700
|
+
LLVMUtil::isStackAllocExtCall(SVFUtil::cast<Instruction>(val)))
|
|
701
|
+
{
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
// Return false if none of the above conditions are met
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
|
|
673
708
|
bool LLVMUtil::isNonInstricCallSite(const Instruction* inst)
|
|
674
709
|
{
|
|
675
710
|
bool res = false;
|
|
@@ -282,7 +282,7 @@ void SVFIRBuilder::initialiseNodes()
|
|
|
282
282
|
llvmModuleSet()->setValueAttr(llvmValue,pag->getGNode(iter->second));
|
|
283
283
|
}
|
|
284
284
|
// Check if the value is an alloca instruction and add a stack object node
|
|
285
|
-
else if (
|
|
285
|
+
else if (LLVMUtil::isStackObj(llvmValue))
|
|
286
286
|
{
|
|
287
287
|
const SVFFunction* f =
|
|
288
288
|
SVFUtil::cast<SVFInstruction>(iter->first)->getFunction();
|
|
@@ -724,13 +724,13 @@ void SymbolTableBuilder::analyzeObjType(ObjTypeInfo* typeinfo, const Value* val)
|
|
|
724
724
|
|
|
725
725
|
/*!
|
|
726
726
|
* Analyze byte size of heap alloc function (e.g. malloc/calloc/...)
|
|
727
|
-
* 1) __attribute__((annotate("
|
|
727
|
+
* 1) __attribute__((annotate("ALLOC_HEAP_RET"), annotate("AllocSize:Arg0")))
|
|
728
728
|
void* safe_malloc(unsigned long size).
|
|
729
729
|
Byte Size is the size(Arg0)
|
|
730
|
-
2)__attribute__((annotate("
|
|
730
|
+
2)__attribute__((annotate("ALLOC_HEAP_RET"), annotate("AllocSize:Arg0*Arg1")))
|
|
731
731
|
char* safecalloc(int a, int b)
|
|
732
732
|
Byte Size is a(Arg0) * b(Arg1)
|
|
733
|
-
3)__attribute__((annotate("
|
|
733
|
+
3)__attribute__((annotate("ALLOC_HEAP_RET"), annotate("UNKNOWN")))
|
|
734
734
|
void* __sysv_signal(int a, void *b)
|
|
735
735
|
Byte Size is Unknown
|
|
736
736
|
If all required arg values are constant, byte Size is also constant,
|