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 <cassert>
29#include <sstream>
30#include <fstream>
31
32#include "Graphs/ICFGNode.h"
33#include "Util/cJSON.h"
34#include "Util/SVFBugReport.h"
35#include "Util/SVFUtil.h"
36#include "SVFIR/SVFVariables.h"
37
38
39using namespace std;
40using namespace SVF;
41
42const std::map<GenericBug::BugType, std::string> GenericBug::BugType2Str =
43{
44 {GenericBug::FULLBUFOVERFLOW, "Full Buffer Overflow"},
45 {GenericBug::PARTIALBUFOVERFLOW, "Partial Buffer Overflow"},
46 {GenericBug::NEVERFREE, "Never Free"},
47 {GenericBug::PARTIALLEAK, "Partial Leak"},
48 {GenericBug::FILENEVERCLOSE, "File Never Close"},
49 {GenericBug::FILEPARTIALCLOSE, "File Partial Close"},
50 {GenericBug::DOUBLEFREE, "Double Free"},
51 {GenericBug::FULLNULLPTRDEREFERENCE, "Full Null Ptr Dereference"},
52 {GenericBug::PARTIALNULLPTRDEREFERENCE, "Partial Null Ptr Dereference"}
53};
54
55const std::string GenericBug::getLoc() const
56{
59}
60
61const std::string GenericBug::getFuncName() const
62{
65}
66
82
84{
87 {
88 SVFUtil::errs() << SVFUtil::bugMsg1("\t Full Overflow :") << " accessing at : ("
89 << GenericBug::getLoc() << ")\n";
90
91 }
92 else
93 {
94 SVFUtil::errs() << SVFUtil::bugMsg1("\t Partial Overflow :") << " accessing at : ("
95 << GenericBug::getLoc() << ")\n";
96 }
97 bugInfo << "\t\t allocate size : [" << allocLowerBound << ", " << allocUpperBound << "], ";
98 bugInfo << "access size : [" << accessLowerBound << ", " << accessUpperBound << "]\n";
99 SVFUtil::errs() << "\t\t Info : \n" << bugInfo.str();
100 SVFUtil::errs() << "\t\t Events : \n";
101
102 for(auto event : bugEventStack)
103 {
104 switch(event.getEventType())
105 {
107 {
108 SVFUtil::errs() << "\t\t callsite at : ( " << event.getEventLoc() << " )\n";
109 break;
110 }
111 default:
112 {
113 // TODO: implement more events when needed
114 break;
115 }
116 }
117 }
118}
119
125
127{
128 SVFUtil::errs() << SVFUtil::bugMsg1("\t NeverFree :") << " memory allocation at : ("
129 << GenericBug::getLoc() << ")\n";
130}
131
133{
136 auto lastBranchEventIt = bugEventStack.end() - 1;
137 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
138 {
140 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
141 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
142
143 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
144
147
149 }
150
151 cJSON_AddItemToObject(bugDescription, "ConditionalFreePath", pathInfo);
152
153 return bugDescription;
154}
155
157{
158 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialLeak :") << " memory allocation at : ("
159 << GenericBug::getLoc() << ")\n";
160
161 SVFUtil::errs() << "\t\t conditional free path: \n";
162 auto lastBranchEventIt = bugEventStack.end() - 1;
163 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
164 {
165 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
166 }
167 SVFUtil::errs() << "\n";
168}
169
171{
173
175 auto lastBranchEventIt = bugEventStack.end() - 1;
176 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
177 {
179 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
180 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
181 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
182
185
187 }
189
190 return bugDescription;
191}
192
194{
195 SVFUtil::errs() << SVFUtil::bugMsg2("\t Double Free :") << " memory allocation at : ("
196 << GenericBug::getLoc() << ")\n";
197
198 SVFUtil::errs() << "\t\t double free path: \n";
199 auto lastBranchEventIt = bugEventStack.end() - 1;
200 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
201 {
202 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
203 }
204 SVFUtil::errs() << "\n";
205}
206
212
214{
215 SVFUtil::errs() << SVFUtil::bugMsg1("\t FileNeverClose :") << " file open location at : ("
216 << GenericBug::getLoc() << ")\n";
217}
218
220{
222
224
225 auto lastBranchEventIt = bugEventStack.end() - 1;
226 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
227 {
229 cJSON *branchLoc = cJSON_Parse((*eventIt).getEventLoc().c_str());
230 if(branchLoc == nullptr) branchLoc = cJSON_CreateObject();
231 cJSON *branchCondition = cJSON_CreateString((*eventIt).getEventDescription().c_str());
232
235
237 }
238 cJSON_AddItemToObject(bugDescription, "ConditionalFileClosePath", pathInfo);
239
240 return bugDescription;
241}
242
244{
245 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialFileClose :") << " file open location at : ("
246 << GenericBug::getLoc() << ")\n";
247
248 SVFUtil::errs() << "\t\t conditional file close path: \n";
249 auto lastBranchEventIt = bugEventStack.end() - 1;
250 for(auto eventIt = bugEventStack.begin(); eventIt != lastBranchEventIt; eventIt++)
251 {
252 SVFUtil::errs() << "\t\t --> (" << (*eventIt).getEventLoc() << "|" << (*eventIt).getEventDescription() << ") \n";
253 }
254 SVFUtil::errs() << "\n";
255}
256
262
264{
265 SVFUtil::errs() << SVFUtil::bugMsg2("\t FullNullPtrDereference :") << " dereference at : ("
266 << GenericBug::getLoc() << ")\n";
267}
268
274
276{
277 SVFUtil::errs() << SVFUtil::bugMsg2("\t PartialNullPtrDereference :") << " dereference at : ("
278 << GenericBug::getLoc() << ")\n";
279}
280
281const std::string SVFBugEvent::getFuncName() const
282{
283 return eventInst->getFun()->getName();
284}
285
286const std::string SVFBugEvent::getEventLoc() const
287{
288 return eventInst->getSourceLoc();
289}
290
291const std::string SVFBugEvent::getEventDescription() const
292{
293 switch(getEventType())
294 {
296 {
298 {
299 return "True";
300 }
301 else
302 {
303 return "False";
304 }
305 break;
306 }
308 {
309 std::string description("calls ");
310 assert(SVFUtil::isa<CallICFGNode>(eventInst) && "not a call ICFGNode?");
311 const FunObjVar *callee = SVFUtil::cast<CallICFGNode>(eventInst)->getCalledFunction();
312 if(callee == nullptr)
313 {
314 description += "<unknown>";
315 }
316 else
317 {
318 description += callee->getName();
319 }
320 return description;
321 break;
322 }
324 {
325 return "None";
326 }
327 default:
328 {
329 assert(false && "No such type of event!");
330 abort();
331 }
332 }
333}
334
336{
337 for(auto bugIt: bugSet)
338 {
339 delete bugIt;
340 }
341}
342
343void SVFBugReport::dumpToJsonFile(const std::string& filePath) const
344{
345 std::map<u32_t, std::string> eventType2Str =
346 {
347 {SVFBugEvent::CallSite, "call site"},
348 {SVFBugEvent::Caller, "caller"},
349 {SVFBugEvent::Loop, "loop"},
350 {SVFBugEvent::Branch, "branch"}
351 };
352
353 ofstream jsonFile(filePath, ios::out);
354
355 jsonFile << "{\n";
356
358 jsonFile << "\"Defects\": [\n";
359 size_t commaCounter = bugSet.size() - 1;
360 for (auto bugPtr : bugSet)
361 {
363
365 cJSON *bugType = cJSON_CreateString(
366 GenericBug::BugType2Str.at(bugPtr->getBugType()).c_str());
367 cJSON_AddItemToObject(singleDefect, "DefectType", bugType);
368
369 cJSON *bugLoc = cJSON_Parse(bugPtr->getLoc().c_str());
370 if (bugLoc == nullptr)
371 {
372 bugLoc = cJSON_CreateObject();
373 }
374 cJSON_AddItemToObject(singleDefect, "Location", bugLoc);
375
377 bugPtr->getFuncName().c_str());
379
380 cJSON_AddItemToObject(singleDefect, "Description",
381 bugPtr->getBugDescription());
382
385 const GenericBug::EventStack &bugEventStack = bugPtr->getEventStack();
387 {
388 // Add only when bug is context sensitive
389 for (const SVFBugEvent &event : bugEventStack)
390 {
391 if (event.getEventType() == SVFBugEvent::SourceInst)
392 {
393 continue;
394 }
395
397 // Event type
399 eventType2Str[event.getEventType()].c_str());
401 // Function name
403 event.getFuncName().c_str());
405 // Event loc
406 cJSON *eventLoc = cJSON_Parse(event.getEventLoc().c_str());
407 if (eventLoc == nullptr)
408 {
410 }
412 // Event description
414 event.getEventDescription().c_str());
416
418 }
419 }
421
425 if (commaCounter != 0)
426 {
427 jsonFile << ",\n";
428 }
429 commaCounter--;
430
433 }
434 jsonFile << "\n],\n";
435
437 jsonFile << "\"Time\": " << time << ",\n";
438 jsonFile << "\"Memory\": \"" << mem << "\",\n";
439 jsonFile << "\"Coverage\": " << coverage << "\n";
440
441 jsonFile << "}";
442 jsonFile.close();
443}
#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 OrderedMap< 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 FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:75
cJSON * getBugDescription() const
void printBugToTerminal() const
void printBugToTerminal() const
cJSON * getBugDescription() 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
virtual const std::string getSourceLoc() const
Definition SVFValue.h:196
virtual const std::string & getName() const
Definition SVFValue.h:186
std::string bugMsg1(const std::string &msg)
Definition SVFUtil.cpp:87
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
std::string bugMsg2(const std::string &msg)
Definition SVFUtil.cpp:92
for isBitcode
Definition BasicTypes.h:70
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
Definition cJSON.h:104