@@ -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 }"
5597void 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
67147void 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(..,..))
75211bool 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+ }
77217return false ;
78218}
79219
0 commit comments