Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVFBugReport.cpp
Go to the documentation of this file.
1//===- SVFBugReport.cpp -- Base class for statistics---------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23
24//
25// Created by JoelYang on 2023/4/19.
26//
27
28#include "Util/SVFBugReport.h"
29#include <cassert>
30#include "Util/cJSON.h"
31#include "Util/SVFUtil.h"
32#include <sstream>
33#include <fstream>
34
35using namespace std;
36using namespace SVF;
37
38const std::map<GenericBug::BugType, std::string> GenericBug::BugType2Str =
39{
40 {GenericBug::FULLBUFOVERFLOW, "Full Buffer Overflow"},
41 {GenericBug::PARTIALBUFOVERFLOW, "Partial Buffer Overflow"},
42 {GenericBug::NEVERFREE, "Never Free"},
43 {GenericBug::PARTIALLEAK, "Partial Leak"},
44 {GenericBug::FILENEVERCLOSE, "File Never Close"},
45 {GenericBug::FILEPARTIALCLOSE, "File Partial Close"},
46 {GenericBug::DOUBLEFREE, "Double Free"},
47 {GenericBug::FULLNULLPTRDEREFERENCE, "Full Null Ptr Dereference"},
48 {GenericBug::PARTIALNULLPTRDEREFERENCE, "Partial Null Ptr Dereference"}
49};
50
51const std::string GenericBug::getLoc() const
52{
55}
56
57const std::string GenericBug::getFuncName() const
58{
61}
62
78
80{
83 {
84 SVFUtil::errs() << SVFUtil::bugMsg1("\t Full Overflow :") << " accessing at : ("
85 << GenericBug::getLoc() << ")\n";
86
87 }
88 else
89 {
90 SVFUtil::errs() << SVFUtil::bugMsg1("\t Partial Overflow :") << " accessing at : ("
91 << GenericBug::getLoc() << ")\n";
92 }
93 bugInfo << "\t\t allocate size : [" << allocLowerBound << ", " << allocUpperBound << "], ";
94 bugInfo << "access size : [" << accessLowerBound << ", " << accessUpperBound << "]\n";
95 SVFUtil::errs() << "\t\t Info : \n" << bugInfo.str();
96 SVFUtil::errs() << "\t\t Events : \n";
97
98 for(auto event : bugEventStack)
99 {
100 switch(event.getEventType())
101 {
103 {
104 SVFUtil::errs() << "\t\t callsite at : ( " << event.getEventLoc() << " )\n";
105 break;
106 }
107 default:
108 {
109 // TODO: implement more events when needed
110 break;
111 }
112 }
113 }
114}
115
121
123{
124 SVFUtil::errs() << SVFUtil::bugMsg1("\t NeverFree :") << " memory allocation at : ("
125 << GenericBug::getLoc() << ")\n";
126}
127
129{
132 auto lastBranchEventIt = bugEventStack.end() - 1;
133 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
134 {
136 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
137 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
138
139 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
140
143
145 }
146
147 cJSON_AddItemToObject(bugDescription, "ConditionalFreePath", pathInfo);
148
149 return bugDescription;
150}
151
153{
154 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialLeak :") << " memory allocation at : ("
155 << GenericBug::getLoc() << ")\n";
156
157 SVFUtil::errs() << "\t\t conditional free path: \n";
158 auto lastBranchEventIt = bugEventStack.end() - 1;
159 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
160 {
161 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
162 }
163 SVFUtil::errs() << "\n";
164}
165
167{
169
171 auto lastBranchEventIt = bugEventStack.end() - 1;
172 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
173 {
175 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
176 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
177 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
178
181
183 }
185
186 return bugDescription;
187}
188
190{
191 SVFUtil::errs() << SVFUtil::bugMsg2("\t Double Free :") << " memory allocation at : ("
192 << GenericBug::getLoc() << ")\n";
193
194 SVFUtil::errs() << "\t\t double free path: \n";
195 auto lastBranchEventIt = bugEventStack.end() - 1;
196 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
197 {
198 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
199 }
200 SVFUtil::errs() << "\n";
201}
202
208
210{
211 SVFUtil::errs() << SVFUtil::bugMsg1("\t FileNeverClose :") << " file open location at : ("
212 << GenericBug::getLoc() << ")\n";
213}
214
216{
218
220
221 auto lastBranchEventIt = bugEventStack.end() - 1;
222 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
223 {
225 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
226 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
227 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
228
231
233 }
234 cJSON_AddItemToObject(bugDescription, "ConditionalFileClosePath", pathInfo);
235
236 return bugDescription;
237}
238
240{
241 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialFileClose :") << " file open location at : ("
242 << GenericBug::getLoc() << ")\n";
243
244 SVFUtil::errs() << "\t\t conditional file close path: \n";
245 auto lastBranchEventIt = bugEventStack.end() - 1;
246 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
247 {
248 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
249 }
250 SVFUtil::errs() << "\n";
251}
252
258
260{
261 SVFUtil::errs() << SVFUtil::bugMsg2("\t FullNullPtrDereference :") << " dereference at : ("
262 << GenericBug::getLoc() << ")\n";
263}
264
270
272{
273 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialNullPtrDereference :") << " dereference at : ("
274 << GenericBug::getLoc() << ")\n";
275}
276
277const std::string SVFBugEvent::getFuncName() const
278{
279 return eventInst->getFun()->getName();
280}
281
282const std::string SVFBugEvent::getEventLoc() const
283{
284 return eventInst->getSourceLoc();
285}
286
287const std::string SVFBugEvent::getEventDescription() const
288{
289 switch(getEventType())
290 {
292 {
294 {
295 return "True";
296 }
297 else
298 {
299 return "False";
300 }
301 break;
302 }
304 {
305 std::string description("calls ");
306 assert(SVFUtil::isa<CallICFGNode>(eventInst) && "not a call ICFGNode?");
307 const SVFFunction *callee = SVFUtil::cast<CallICFGNode>(eventInst)->getCalledFunction();
308 if(callee == nullptr)
309 {
310 description += "<unknown>";
311 }
312 else
313 {
314 description += callee->getName();
315 }
316 return description;
317 break;
318 }
320 {
321 return "None";
322 }
323 default:
324 {
325 assert(false && "No such type of event!");
326 abort();
327 }
328 }
329}
330
332{
333 for(auto bugIt: bugSet)
334 {
335 delete bugIt;
336 }
337}
338
339void SVFBugReport::dumpToJsonFile(const std::string& filePath) const
340{
341 std::map<u32_t, std::string> eventType2Str =
342 {
343 {SVFBugEvent::CallSite, "call site"},
344 {SVFBugEvent::Caller, "caller"},
345 {SVFBugEvent::Loop, "loop"},
346 {SVFBugEvent::Branch, "branch"}
347 };
348
349 ofstream jsonFile(filePath, ios::out);
350
351 jsonFile << "{\n";
352
354 jsonFile << "\"Defects\": [\n";
355 size_t commaCounter = bugSet.size() - 1;
356 for (auto bugPtr : bugSet)
357 {
359
361 cJSON *bugType = cJSON_CreateString(
362 GenericBug::BugType2Str.at(bugPtr->getBugType()).c_str());
363 cJSON_AddItemToObject(singleDefect, "DefectType", bugType);
364
365 cJSON *bugLoc = cJSON_Parse(bugPtr->getLoc().c_str());
366 if (bugLoc == nullptr)
367 {
368 bugLoc = cJSON_CreateObject();
369 }
370 cJSON_AddItemToObject(singleDefect, "Location", bugLoc);
371
373 bugPtr->getFuncName().c_str());
375
376 cJSON_AddItemToObject(singleDefect, "Description",
377 bugPtr->getBugDescription());
378
381 const GenericBug::EventStack &bugEventStack = bugPtr->getEventStack();
383 {
384 // Add only when bug is context sensitive
385 for (const SVFBugEvent &event : bugEventStack)
386 {
387 if (event.getEventType() == SVFBugEvent::SourceInst)
388 {
389 continue;
390 }
391
393 // Event type
395 eventType2Str[event.getEventType()].c_str());
397 // Function name
399 event.getFuncName().c_str());
401 // Event loc
402 cJSON *eventLoc = cJSON_Parse(event.getEventLoc().c_str());
403 if (eventLoc == nullptr)
404 {
406 }
408 // Event description
410 event.getEventDescription().c_str());
412
414 }
415 }
417
421 if (commaCounter != 0)
422 {
423 jsonFile << ",\n";
424 }
425 commaCounter--;
426
429 }
430 jsonFile << "\n],\n";
431
433 jsonFile << "\"Time\": " << time << ",\n";
434 jsonFile << "\"Memory\": \"" << mem << "\",\n";
435 jsonFile << "\"Coverage\": " << coverage << "\n";
436
437 jsonFile << "}";
438 jsonFile.close();
439}
#define BRANCHFLAGMASK
cJSON_Delete(null)
cJSON * getBugDescription() const
static bool classof(const GenericBug *bug)
ClassOf.
void printBugToTerminal() const
cJSON * getBugDescription() const
void printBugToTerminal() const
cJSON * getBugDescription() const
void printBugToTerminal() const
cJSON * getBugDescription() const
static bool classof(const GenericBug *bug)
ClassOf.
static const std::map< GenericBug::BugType, std::string > BugType2Str
const std::string getLoc() const
returns bug location as json format string
const EventStack bugEventStack
std::vector< SVFBugEvent > EventStack
const std::string getFuncName() const
return bug source function name
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
cJSON * getBugDescription() const
void printBugToTerminal() const
void printBugToTerminal() const
cJSON * getBugDescription() const
virtual const std::string getSourceLoc() const
virtual const std::string getEventLoc() const
virtual const std::string getEventDescription() const
u32_t getEventType() const
const ICFGNode * eventInst
virtual const std::string getFuncName() const
void dumpToJsonFile(const std::string &filePath) const
const std::string & getName() const
Definition SVFValue.h:243
std::string bugMsg1(const std::string &msg)
Definition SVFUtil.cpp:82
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
std::string bugMsg2(const std::string &msg)
Definition SVFUtil.cpp:87
for isBitcode
Definition BasicTypes.h:68
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
Definition cJSON.h:104