Skip to content

Commit b8006b7

Browse files
author
bjjwwang
committed
finally check the version
1 parent f861f87 commit b8006b7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+4466
-743
lines changed

.github/workflows/build.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,15 @@ jobs:
3939
- name: env-setup
4040
run: |
4141
npm install svf-lib
42+
43+
# set python version
44+
- name: Set up Python 3.10
45+
uses: actions/setup-python@v4
46+
with:
47+
python-version: '3.10'
48+
4249
# set SVF_DIR, LLVM_DIR and Z3_DIR and build
43-
- name: build
50+
- name: build and ctest
4451
run: |
4552
export SVF_DIR=$(npm root)/SVF
4653
export LLVM_DIR=$(npm root)/llvm-16.0.0.obj
@@ -50,3 +57,21 @@ jobs:
5057
echo "Z3_DIR="$Z3_DIR
5158
cmake .
5259
make
60+
ctest -V
61+
62+
- name: Install Python dependencies
63+
run: |
64+
pip install --upgrade pip
65+
pip install wheel pybind11 notebook nbconvert nbclient ipykernel build z3-solver
66+
pip install pysvf -i https://test.pypi.org/simple/
67+
68+
- name: Register Jupyter kernel
69+
run: |
70+
python -m ipykernel install --user --name python3
71+
72+
- name: Run all notebooks in current directory
73+
run: |
74+
for nb in $(find . -maxdepth 2 -name "*-Solution.ipynb") ; do
75+
echo "Executing $nb..."
76+
jupyter nbconvert --to notebook --execute "$nb" --stdout > /dev/null
77+
done

Assignment-1/CPP/Assignment-1.cpp

Lines changed: 147 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,96 @@ using namespace std;
4444
/// You will need to collect each path from src to snk and then add the path to the `paths` set.
4545
/// Add each path (a sequence of node IDs) as a string into std::set<std::string> paths
4646
/// in the format "START->1->2->4->5->END", where -> indicate an ICFGEdge connects two ICFGNode IDs
47-
void ICFGTraversal::reachability(const ICFGNode* curNode, const ICFGNode* snk) {
48-
/// TODO: your code starts from here
47+
void ICFGTraversal::reachability(const ICFGNode* src, const ICFGNode* dst) {
48+
const std::pair<const ICFGNode *, CallStack> curItem = std::make_pair(
49+
src, callstack);
50+
if (visited.count(curItem)) return;
51+
visited.insert(curItem);
52+
path.push_back(src->getId());
53+
54+
if (src == dst) {
55+
std::string singlePath = "START->";
56+
for (unsigned node : path)
57+
{
58+
singlePath.append(std::to_string(node));
59+
singlePath.append("->");
60+
}
61+
singlePath += "END";
62+
paths.insert(singlePath);
63+
}
64+
for (const ICFGEdge *edge: src->getOutEdges()) {
65+
if (edge->isIntraCFGEdge()) {
66+
reachability(edge->getDstNode(), dst);
67+
} else if (const CallCFGEdge *callEdge = SVFUtil::dyn_cast<CallCFGEdge>(edge)) {
68+
callstack.push_back(callEdge->getSrcNode());
69+
reachability(edge->getDstNode(), dst);
70+
callstack.pop_back();
71+
} else if (const RetICFGNode *retNode = SVFUtil::dyn_cast<RetICFGNode>(edge->getDstNode())) {
72+
if (!callstack.empty() && (callstack.back() == retNode->getCallICFGNode())) {
73+
callstack.pop_back();
74+
reachability(edge->getDstNode(), dst);
75+
callstack.push_back(retNode->getCallICFGNode());
76+
} else if (callstack.empty()) {
77+
reachability(edge->getDstNode(), dst);
78+
}
79+
}
80+
}
81+
path.pop_back();
82+
visited.erase(curItem);
83+
}
84+
85+
86+
// Helper function to extract data enclosed in braces
87+
string extractDataFromBraces(const string &str) {
88+
int leftBrace = str.find("{") + 1;
89+
int rightBrace = str.find("}", leftBrace);
90+
return str.substr(leftBrace, rightBrace - leftBrace);
4991
}
5092

5193
/// TODO: Implement your code to parse the two lines to identify sources and sinks from `SrcSnk.txt` for your
52-
/// reachability analysis The format in SrcSnk.txt is in the form of
53-
/// line 1 for sources "{ api1 api2 api3 }"
94+
/// reachability analysis The format in SrcSnk.txt is in the form of
95+
/// line 1 for sources "{ api1 api2 api3 }"
5496
/// line 2 for sinks "{ api1 api2 api3 }"
5597
void ICFGTraversal::readSrcSnkFromFile(const string& filename) {
56-
/// TODO: your code starts from here
98+
// Open the file
99+
ifstream fileHandler(filename);
100+
101+
// Check if the file is successfully opened
102+
if (!fileHandler.is_open()) {
103+
cerr << "Error opening file: " << filename << endl;
104+
return;
105+
}
106+
107+
string temp, sourcesLine, sinksLine;
108+
bool isSourceLine = true;
109+
110+
// Read the file line by line
111+
while (getline(fileHandler, temp)) {
112+
// Alternate between reading source and sink lines
113+
if (isSourceLine) {
114+
sourcesLine = temp;
115+
} else {
116+
sinksLine = temp;
117+
}
118+
isSourceLine = !isSourceLine;
119+
}
120+
121+
// Extract and process sources and sinks
122+
string sources = extractDataFromBraces(sourcesLine);
123+
string sinks = extractDataFromBraces(sinksLine);
124+
125+
// Parse and insert source APIs into the set
126+
stringstream sourcesStream(sources);
127+
while (sourcesStream >> temp) {
128+
checker_source_api.insert(temp);
129+
}
130+
131+
// Parse and insert sink APIs into the set
132+
stringstream sinksStream(sinks);
133+
while (sinksStream >> temp) {
134+
checker_sink_api.insert(temp);
135+
}
136+
57137
}
58138

59139
// TODO: Implement your Andersen's Algorithm here
@@ -65,15 +145,75 @@ void ICFGTraversal::readSrcSnkFromFile(const string& filename) {
65145
/// q <--GEP, fld-- p => for each o ∈ pts(p) : pts(q) = pts(q) ∪ {o.fld}
66146
/// pts(q) denotes the points-to set of q
67147
void AndersenPTA::solveWorklist() {
68-
/// TODO: your code starts from here
148+
for (ConstraintGraph::const_iterator nodeIt = consCG->begin(), nodeEit = consCG->end();
149+
nodeIt != nodeEit; nodeIt++) {
150+
ConstraintNode *cgNode = nodeIt->second;
151+
for (ConstraintEdge *edge: cgNode->getAddrInEdges()) {
152+
const AddrCGEdge *addr = SVFUtil::cast<AddrCGEdge>(edge);
153+
NodeID dst = addr->getDstID();
154+
NodeID src = addr->getSrcID();
155+
if (addPts(dst, src))
156+
pushIntoWorklist(dst);
157+
}
158+
}
159+
160+
// Keep solving until workList is empty.
161+
while (!isWorklistEmpty()) {
162+
NodeID nodeId = popFromWorklist();
163+
ConstraintNode *node = consCG->getConstraintNode(nodeId);
164+
165+
/// foreach o \in pts(p)
166+
for (NodeID o: getPts(nodeId)) {
167+
168+
/// *p = q pts(q) \subseteq pts(o)
169+
for (ConstraintEdge *edge: node->getStoreInEdges()) {
170+
if (addCopyEdge(edge->getSrcID(), o)) {
171+
pushIntoWorklist(edge->getSrcID());
172+
}
173+
}
174+
// r = *p pts(o) \subseteq pts(r)
175+
for (ConstraintEdge *edge: node->getLoadOutEdges()) {
176+
if (addCopyEdge(o, edge->getDstID())) {
177+
pushIntoWorklist(o);
178+
}
179+
}
180+
}
181+
182+
/// q = p pts(p) \subseteq pts(q)
183+
for (ConstraintEdge *edge: node->getCopyOutEdges()) {
184+
if (unionPts(edge->getDstID(), edge->getSrcID())) {
185+
pushIntoWorklist(edge->getDstID());
186+
}
187+
}
188+
189+
/// q = &p->f pts(p.f) \subseteq pts(q)
190+
for (ConstraintEdge *edge: node->getGepOutEdges()) {
191+
PointsTo fieldObjs;
192+
if(NormalGepCGEdge* gepEdge = SVFUtil::dyn_cast<NormalGepCGEdge>(edge))
193+
{
194+
for(NodeID o: getPts(edge->getSrcID()))
195+
{
196+
NodeID fld = consCG->getGepObjVar(o, gepEdge->getAccessPath().getConstantStructFldIdx());
197+
fieldObjs.set(fld);
198+
}
199+
}
200+
if (unionPts(edge->getDstID(), fieldObjs)) {
201+
pushIntoWorklist(edge->getDstID());
202+
}
203+
}
204+
}
69205
}
70206

71207
/// TODO: Checking aliases of the two variables at source and sink. For example:
72208
/// src instruction: actualRet = source();
73209
/// snk instruction: sink(actualParm,...);
74210
/// return true if actualRet is aliased with any parameter at the snk node (e.g., via ander->alias(..,..))
75211
bool ICFGTraversal::aliasCheck(const CallICFGNode* src, const CallICFGNode* snk) {
76-
/// TODO: your code starts from here
212+
for (const SVFVar *node: snk->getActualParms()) {
213+
if (ander->alias(src->getRetICFGNode()->getActualRet()->getId(), node->getId())) {
214+
return true;
215+
}
216+
}
77217
return false;
78218
}
79219

Assignment-1/CPP/test.cpp

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
#include "Util/Options.h"
88

99
using namespace std;
10+
void checkICFGcase(std::string moduleName, const std::set<std::string>& res, const std::set<std::string>& expected) {
11+
std::stringstream ss;
12+
ss << "\n wrong paths generated - " << moduleName << " failed !";
13+
assert(res.size() == expected.size() && ss.str().c_str());
14+
for (auto path : res) {
15+
assert(expected.find(path) != expected.end() && ss.str().c_str());
16+
}
17+
}
1018

1119
void TestICFG(std::vector<std::string>& moduleNameVec) {
1220
LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(moduleNameVec);
@@ -17,26 +25,76 @@ void TestICFG(std::vector<std::string>& moduleNameVec) {
1725
ICFG* icfg = pag->getICFG();
1826
// If you want to test your own case, please change the dump name
1927
ICFGTraversal* gt = new ICFGTraversal(pag);
20-
const fs::path& config = CUR_DIR() / "../SrcSnk.txt";
28+
const fs::path& config = CUR_DIR() / "../Tests/SrcSnk.txt";
2129
gt->readSrcSnkFromFile(config);
2230
for (const CallICFGNode* src : gt->identifySources()) {
2331
for (const CallICFGNode* snk : gt->identifySinks()) {
2432
gt->reachability(src, snk);
2533
}
2634
}
2735
std::string moduleName = moduleNameVec[0].substr(moduleNameVec[0].find_last_of('/') + 1);
36+
2837
if (moduleName == "test1.ll") {
29-
std::set<std::string> expected = {"START->6->7->8->9->10->1->5->2->11->14->END",
30-
"START->6->7->8->9->12->1->5->2->13->16->END"};
38+
std::set<std::string> expected = {"START->3->4->5->END"};
3139
assert(gt->getPaths() == expected && " \n wrong paths generated - test1 failed !");
40+
checkICFGcase(moduleName, gt->getPaths(), expected);
3241
}
3342
else if (moduleName == "test2.ll") {
43+
std::set<std::string> expected = {"START->3->4->5->6->7->8->9->END",
44+
"START->3->4->5->6->7->END", "START->5->6->7->8->9->END",
45+
"START->5->6->7->END"};
46+
checkICFGcase(moduleName, gt->getPaths(), expected);
47+
}
48+
else if (moduleName == "test3.ll") {
49+
std::set<std::string> expected = {"START->6->7->8->1->5->2->9->10->END"};
50+
checkICFGcase(moduleName, gt->getPaths(), expected);
51+
}
52+
else if (moduleName == "test4.ll") {
53+
std::set<std::string> expected = {"START->12->13->14->3->8->9->1->7->2->10->11->4->15->16->END"};
54+
checkICFGcase(moduleName, gt->getPaths(), expected);
55+
}
56+
else if (moduleName == "test5.ll") {
57+
std::set<std::string> expected =
58+
{
59+
"START->6->7->8->9->10->1->5->2->11->14->END",
60+
"START->6->7->8->9->12->1->5->2->13->16->END",
61+
};
62+
checkICFGcase(moduleName, gt->getPaths(), expected);
63+
}
64+
else if (moduleName == "test6.ll") {
65+
std::set<std::string> expected =
66+
{
67+
"START->12->13->14->15->16->3->8->9->1->7->2->10->11->4->17->20->END",
68+
"START->12->13->14->15->18->3->8->9->1->7->2->10->11->4->19->22->END",
69+
};
70+
checkICFGcase(moduleName, gt->getPaths(), expected);
71+
}
72+
else if (moduleName == "test7.ll") {
73+
//START->16->1->2->END
3474
std::set<std::string> expected = {"START->17->1->7->END"};
35-
assert(gt->getPaths().size() == expected.size() && " \n wrong paths generated - test2 failed !");
36-
for (auto path : gt->getPaths()) {
37-
assert(expected.find(path) != expected.end() && " \n wrong paths generated - test2 failed !");
38-
}
75+
checkICFGcase(moduleName, gt->getPaths(), expected);
76+
}
77+
else if (moduleName == "test8.ll") {
78+
std::set<std::string> expected =
79+
{
80+
"START->6->7->8->9->10->1->5->2->11->14->END",
81+
"START->6->7->8->9->12->1->5->2->13->16->END",
82+
};
83+
checkICFGcase(moduleName, gt->getPaths(), expected);
84+
}
85+
else if (moduleName == "test9.ll") {
86+
std::set<std::string> expected = {"START->7->8->9->10->11->14->END"};
87+
checkICFGcase(moduleName, gt->getPaths(), expected);
3988
}
89+
else if (moduleName == "test10.ll") {
90+
std::set<std::string> expected =
91+
{
92+
"START->3->4->5->6->7->9->11->END",
93+
"START->3->4->5->6->8->10->14->17->END",
94+
};
95+
checkICFGcase(moduleName, gt->getPaths(), expected);
96+
}
97+
4098

4199
for (auto path : gt->getPaths())
42100
std::cerr << path << "\n";
@@ -107,13 +165,13 @@ void TestTaint(std::vector<std::string>& moduleNameVec) {
107165
std::string moduleName = moduleNameVec[0].substr(moduleNameVec[0].find_last_of('/') + 1);
108166
if (moduleName == "test1.ll") {
109167
set<string> expected = {"START->6->1->5->2->7->8->9->10->END"};
110-
assert(taint->getPaths() == expected && " \n Wrong paths generated - Test1 failed !");
111-
cout << "\n Test1 passed !" << endl;
168+
assert(taint->getPaths() == expected && " \n wrong paths generated - test1 failed !");
169+
cout << "\n test1 passed !" << endl;
112170
}
113-
else if (moduleName == "test2.ll") {
171+
else if (moduleName == "test4.ll") {
114172
set<string> expected = {"START->6->1->5->2->7->8->9->10->11->13->14->END"};
115-
assert(taint->getPaths() == expected && " \n Wrong paths generated - Test4 failed !");
116-
cout << "\n Test2 passed !" << endl;
173+
assert(taint->getPaths() == expected && " \n wrong paths generated - test4 failed !");
174+
cout << "\n test2 passed !" << endl;
117175
}
118176
SVF::SVFIR::releaseSVFIR();
119177
SVF::LLVMModuleSet::releaseLLVMModuleSet();

0 commit comments

Comments
 (0)