Static Value-Flow Analysis
Loading...
Searching...
No Matches
AEDetector.cpp
Go to the documentation of this file.
1//===- AEDetector.cpp -- Vulnerability Detectors---------------------------------//
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 Jiawei Wang on 2024/8/20.
26//
27
29#include <AE/Svfexe/AbsExtAPI.h>
32
33using namespace SVF;
45{
46 if (!SVFUtil::isa<CallICFGNode>(node))
47 {
48 // Handle non-call nodes by analyzing GEP instructions
49 for (const SVFStmt* stmt : node->getSVFStmts())
50 {
51 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
52 {
53 SVFIR* svfir = PAG::getPAG();
54 NodeID lhs = gep->getLHSVarID();
55 NodeID rhs = gep->getRHSVarID();
56
57 // Update the GEP object offset from its base
58 updateGepObjOffsetFromBase(as, as[lhs].getAddrs(), as[rhs].getAddrs(), as.getByteOffset(gep));
59
61 AddressValue objAddrs = as[gep->getRHSVarID()].getAddrs();
62 for (const auto& addr : objAddrs)
63 {
64 NodeID objId = as.getIDFromAddr(addr);
65 u32_t size = 0;
66 // like `int arr[10]` which has constant size before runtime
68 {
69 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
70 }
71 else
72 {
73 // like `int len = ***; int arr[len]`, whose size can only be known in runtime
75 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
76 {
77 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
78 {
79 size = as.getAllocaInstByteSize(addrStmt);
80 }
81 }
82 }
83
84 // Calculate access offset and check for potential overflow
86 if (accessOffset.ub().getIntNumeral() >= size)
87 {
88 AEException bug(stmt->toString());
89 addBugToReporter(bug, stmt->getICFGNode());
90 }
91 }
92 }
93 }
94 }
95 else
96 {
97 // Handle call nodes by checking for external API calls
98 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
99 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
100 {
102 }
103 }
104}
105
106
115{
116 // get function name
117 std::string funcName = callNode->getCalledFunction()->getName();
118 if (funcName == "SAFE_BUFACCESS")
119 {
120 // void SAFE_BUFACCESS(void* data, int size);
122 if (callNode->arg_size() < 2)
123 return;
126 callNode);
127 u32_t size_id = callNode->getArgument(1)->getId();
128 IntervalValue val = as[size_id].getInterval();
129 if (val.isBottom())
130 {
131 val = IntervalValue(0);
132 assert(false && "SAFE_BUFACCESS size is bottom");
133 }
134 const SVFVar* arg0Val = callNode->getArgument(0);
136 if (isSafe)
137 {
138 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe buffer access at SAFE_BUFACCESS")
139 << " — " << callNode->toString() << "\n";
140 return;
141 }
142 else
143 {
144 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected buffer overflow at SAFE_BUFACCESS")
145 << " — Position: " << callNode->getSourceLoc() << "\n";
146 assert(false);
147 }
148 }
149 else if (funcName == "UNSAFE_BUFACCESS")
150 {
151 // void UNSAFE_BUFACCESS(void* data, int size);
153 if (callNode->arg_size() < 2) return;
155 u32_t size_id = callNode->getArgument(1)->getId();
156 IntervalValue val = as[size_id].getInterval();
157 if (val.isBottom())
158 {
159 assert(false && "UNSAFE_BUFACCESS size is bottom");
160 }
161 const SVFVar* arg0Val = callNode->getArgument(0);
163 if (!isSafe)
164 {
165 SVFUtil::outs() << SVFUtil::sucMsg("success: expected buffer overflow at UNSAFE_BUFACCESS")
166 << " — " << callNode->toString() << "\n";
167 return;
168 }
169 else
170 {
171 SVFUtil::outs() << SVFUtil::errMsg("failure: buffer overflow expected at UNSAFE_BUFACCESS, but none detected")
172 << " — Position: " << callNode->getSourceLoc() << "\n";
173 assert(false);
174 }
175 }
176}
177
185{
186 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
187 extAPIBufOverflowCheckRules["llvm_memcpy_p0_p0_i64"] = {{0, 2}, {1, 2}};
188 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
189 extAPIBufOverflowCheckRules["llvm_memcpy"] = {{0, 2}, {1, 2}};
190 extAPIBufOverflowCheckRules["llvm_memmove"] = {{0, 2}, {1, 2}};
191 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
192 extAPIBufOverflowCheckRules["llvm_memmove_p0_p0_i64"] = {{0, 2}, {1, 2}};
193 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
194 extAPIBufOverflowCheckRules["__memcpy_chk"] = {{0, 2}, {1, 2}};
195 extAPIBufOverflowCheckRules["memmove"] = {{0, 2}, {1, 2}};
196 extAPIBufOverflowCheckRules["bcopy"] = {{0, 2}, {1, 2}};
197 extAPIBufOverflowCheckRules["memccpy"] = {{0, 3}, {1, 3}};
198 extAPIBufOverflowCheckRules["__memmove_chk"] = {{0, 2}, {1, 2}};
199 extAPIBufOverflowCheckRules["llvm_memset"] = {{0, 2}};
200 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i32"] = {{0, 2}};
201 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i64"] = {{0, 2}};
202 extAPIBufOverflowCheckRules["llvm_memset_p0_i64"] = {{0, 2}};
203 extAPIBufOverflowCheckRules["__memset_chk"] = {{0, 2}};
204 extAPIBufOverflowCheckRules["wmemset"] = {{0, 2}};
205 extAPIBufOverflowCheckRules["strncpy"] = {{0, 2}, {1, 2}};
206 extAPIBufOverflowCheckRules["iconv"] = {{1, 2}, {3, 4}};
207}
208
219 const CallICFGNode* call)
220{
221 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
222
224
225 // Determine the type of external memory API
226 for (const std::string &annotation : ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
227 {
228 if (annotation.find("MEMCPY") != std::string::npos)
230 if (annotation.find("MEMSET") != std::string::npos)
232 if (annotation.find("STRCPY") != std::string::npos)
234 if (annotation.find("STRCAT") != std::string::npos)
236 }
237
238 // Apply buffer overflow checks based on the determined API type
240 {
241 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
242 {
243 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
244 return;
245 }
246 std::vector<std::pair<u32_t, u32_t>> args =
248 for (auto arg : args)
249 {
250 IntervalValue offset = as[call->getArgument(arg.second)->getId()].getInterval() - IntervalValue(1);
251 const SVFVar* argVar = call->getArgument(arg.first);
253 {
254 AEException bug(call->toString());
255 addBugToReporter(bug, call);
256 }
257 }
258 }
259 else if (extType == AbsExtAPI::MEMSET)
260 {
261 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
262 {
263 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
264 return;
265 }
266 std::vector<std::pair<u32_t, u32_t>> args =
268 for (auto arg : args)
269 {
270 IntervalValue offset = as[call->getArgument(arg.second)->getId()].getInterval() - IntervalValue(1);
271 const SVFVar* argVar = call->getArgument(arg.first);
273 {
274 AEException bug(call->toString());
275 addBugToReporter(bug, call);
276 }
277 }
278 }
279 else if (extType == AbsExtAPI::STRCPY)
280 {
281 if (!detectStrcpy(as, call))
282 {
283 AEException bug(call->toString());
284 addBugToReporter(bug, call);
285 }
286 }
287 else if (extType == AbsExtAPI::STRCAT)
288 {
289 if (!detectStrcat(as, call))
290 {
291 AEException bug(call->toString());
292 addBugToReporter(bug, call);
293 }
294 }
295 else
296 {
297 // Handle other cases
298 }
299}
300
313{
314 SVFIR* svfir = PAG::getPAG();
315 auto obj = svfir->getGNode(objId);
316
317 if (SVFUtil::isa<BaseObjVar>(obj))
318 {
319 // if the object is a BaseObjVar, return the byte offset directly
320 // like `int arr[10]; arr[5] = 1;` arr is the baseObjVar
321 return as.getByteOffset(gep);
322 }
323 else if (SVFUtil::isa<GepObjVar>(obj))
324 {
325 // if the object is a GepObjVar, return the offset from the base object
326 // like `int arr[10]; int* p=arr+5; p[3] = 1`, p is the GepObjVar from arr.
327 return getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(obj)) + as.getByteOffset(gep);
328 }
329 else
330 {
331 assert(SVFUtil::isa<DummyObjVar>(obj) && "Unknown object type");
332 return IntervalValue::top();
333 }
334}
335
347{
348 SVFIR* svfir = PAG::getPAG();
349
350 for (const auto& objAddr : objAddrs)
351 {
352 NodeID objId = as.getIDFromAddr(objAddr);
353 auto obj = svfir->getGNode(objId);
354
355 if (SVFUtil::isa<BaseObjVar>(obj))
356 {
357 // if the object is a BaseObjVar, add the offset directly
358 // like llvm bc `arr = alloc i8 12; p = gep arr, 4`
359 // we write key value pair {gep, 4}
360 for (const auto& gepAddr : gepAddrs)
361 {
362 NodeID gepObj = as.getIDFromAddr(gepAddr);
363 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getGNode(gepObj)))
364 {
366 }
367 else
368 {
369 assert(AbstractState::isInvalidMem(gepAddr) && "GEP object is neither a GepObjVar nor an invalid memory address");
370 }
371 }
372 }
373 else if (SVFUtil::isa<GepObjVar>(obj))
374 {
375 // if the object is a GepObjVar, add the offset from the base object
376 // like llvm bc `arr = alloc i8 12; p = gep arr, 4; q = gep p, 6`
377 // we retreive {p, 4} and write {q, 4+6}
378 const GepObjVar* objVar = SVFUtil::cast<GepObjVar>(obj);
379 for (const auto& gepAddr : gepAddrs)
380 {
381 NodeID gepObj = as.getIDFromAddr(gepAddr);
382 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getGNode(gepObj)))
383 {
385 {
391 }
392 else
393 {
394 assert(false &&
395 "GEP RHS object has no offset from base");
396 }
397 }
398 else
399 {
400 assert(AbstractState::isInvalidMem(gepAddr) && "GEP object is neither a GepObjVar nor an invalid memory address");
401 }
402 }
403 }
404 }
405}
406
424
436{
437 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
438 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
439
440 if (std::find(strcatGroup.begin(), strcatGroup.end(), call->getCalledFunction()->getName()) != strcatGroup.end())
441 {
442 const SVFVar* arg0Val = call->getArgument(0);
443 const SVFVar* arg1Val = call->getArgument(1);
448 }
449 else if (std::find(strncatGroup.begin(), strncatGroup.end(), call->getCalledFunction()->getName()) != strncatGroup.end())
450 {
451 const SVFVar* arg0Val = call->getArgument(0);
452 const SVFVar* arg2Val = call->getArgument(2);
453 IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
457 }
458 else
459 {
460 assert(false && "Unknown strcat function, please add it to strcatGroup or strncatGroup");
461 abort();
462 }
463}
464
477{
478 SVFIR* svfir = PAG::getPAG();
479 NodeID value_id = value->getId();
480
481 assert(as[value_id].isAddr());
482 for (const auto& addr : as[value_id].getAddrs())
483 {
484 NodeID objId = as.getIDFromAddr(addr);
485 u32_t size = 0;
486 // if the object is a constant size object, get the size directly
488 {
489 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
490 }
491 else
492 {
493 // if the object is not a constant size object, get the size from the addrStmt
494 const ICFGNode* addrNode = svfir->getBaseObject(objId)->getICFGNode();
495 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
496 {
497 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
498 {
499 size = as.getAllocaInstByteSize(addrStmt);
500 }
501 }
502 }
503
505 // if the object is a GepObjVar, get the offset from the base object
506 if (SVFUtil::isa<GepObjVar>(svfir->getGNode(objId)))
507 {
508 offset = getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(svfir->getGNode(objId))) + len;
509 }
510 else if (SVFUtil::isa<BaseObjVar>(svfir->getGNode(objId)))
511 {
512 // if the object is a BaseObjVar, get the offset directly
513 offset = len;
514 }
515
516 // if the offset is greater than the size, return false
517 if (offset.ub().getIntNumeral() >= size)
518 {
519 return false;
520 }
521 }
522 return true;
523}
524
526{
527 if (SVFUtil::isa<CallICFGNode>(node))
528 {
529 // external API like memset(*dst, elem, sz)
530 // we check if it's external api and check the corrisponding index
531 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
532 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
533 {
535 }
536 }
537 else
538 {
539 for (const auto& stmt: node->getSVFStmts())
540 {
541 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
542 {
543 // like llvm bitcode `p = gep p, idx`
544 // we check rhs p's all address are valid mem
545 SVFVar* rhs = gep->getRHSVar();
546 if (!canSafelyDerefPtr(as, rhs))
547 {
548 AEException bug(stmt->toString());
549 addBugToReporter(bug, stmt->getICFGNode());
550 }
551 }
552 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
553 {
554 // like llvm bitcode `p = load q`
555 // we check lhs p's all address are valid mem
556 SVFVar* lhs = load->getLHSVar();
557 if ( !canSafelyDerefPtr(as, lhs))
558 {
559 AEException bug(stmt->toString());
560 addBugToReporter(bug, stmt->getICFGNode());
561 }
562 }
563 }
564 }
565}
566
567
569{
570 std::string funcName = callNode->getCalledFunction()->getName();
571 if (funcName == "UNSAFE_LOAD")
572 {
573 // void UNSAFE_LOAD(void* ptr);
575 if (callNode->arg_size() < 1)
576 return;
578
579 const SVFVar* arg0Val = callNode->getArgument(0);
580 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)
581 bool isSafe = canSafelyDerefPtr(as, arg0Val) && arg0Val->getId() != 0;
582 if (!isSafe)
583 {
584 SVFUtil::outs() << SVFUtil::sucMsg("success: expected null dereference at UNSAFE_LOAD")
585 << " — " << callNode->toString() << "\n";
586 return;
587 }
588 else
589 {
590 SVFUtil::outs() << SVFUtil::errMsg("failure: null dereference expected at UNSAFE_LOAD, but none detected")
591 << " — Position: " << callNode->getSourceLoc() << "\n";
592 assert(false);
593 }
594 }
595 else if (funcName == "SAFE_LOAD")
596 {
597 // void SAFE_LOAD(void* ptr);
599 if (callNode->arg_size() < 1) return;
601 const SVFVar* arg0Val = callNode->getArgument(0);
602 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)ols
603 bool isSafe = canSafelyDerefPtr(as, arg0Val) && arg0Val->getId() != 0;
604 if (isSafe)
605 {
606 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe dereference at SAFE_LOAD")
607 << " — " << callNode->toString() << "\n";
608 return;
609 }
610 else
611 {
612 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected null dereference at SAFE_LOAD")
613 << " — Position: " << callNode->getSourceLoc() << "\n";
614 assert(false);
615 }
616 }
617}
618
620{
621 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
622 // get ext type
623 // get argument index which are nullptr deref checkpoints for extapi
624 std::vector<u32_t> tmp_args;
625 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
626 {
627 if (annotation.find("MEMCPY") != std::string::npos)
628 {
629 if (call->arg_size() < 4)
630 {
631 // for memcpy(void* dest, const void* src, size_t n)
632 tmp_args.push_back(0);
633 tmp_args.push_back(1);
634 }
635 else
636 {
637 // for unsigned long iconv(void* cd, char **restrict inbuf, unsigned long *restrict inbytesleft, char **restrict outbuf, unsigned long *restrict outbytesleft)
638 tmp_args.push_back(1);
639 tmp_args.push_back(2);
640 tmp_args.push_back(3);
641 tmp_args.push_back(4);
642 }
643 }
644 else if (annotation.find("MEMSET") != std::string::npos)
645 {
646 // for memset(void* dest, elem, sz)
647 tmp_args.push_back(0);
648 }
649 else if (annotation.find("STRCPY") != std::string::npos)
650 {
651 // for strcpy(void* dest, void* src)
652 tmp_args.push_back(0);
653 tmp_args.push_back(1);
654 }
655 else if (annotation.find("STRCAT") != std::string::npos)
656 {
657 // for strcat(void* dest, const void* src)
658 // for strncat(void* dest, const void* src, size_t n)
659 tmp_args.push_back(0);
660 tmp_args.push_back(1);
661 }
662 }
663
664 for (const auto &arg: tmp_args)
665 {
666 if (call->arg_size() <= arg)
667 continue;
668 const SVFVar* argVal = call->getArgument(arg);
670 {
671 AEException bug(call->toString());
672 addBugToReporter(bug, call);
673 }
674 }
675}
676
677
679{
680 NodeID value_id = value->getId();
682 // uninit value cannot be dereferenced, return unsafe
683 if (isUninit(AbsVal)) return false;
684 // Interval Value (non-addr) is not the checkpoint of nullptr dereference, return safe
685 if (!AbsVal.isAddr()) return true;
686 for (const auto &addr: AbsVal.getAddrs())
687 {
688 // if the addr itself is invalid mem, report unsafe
690 return false;
691 // if nullptr is detected, return unsafe
693 return false;
694 // if addr is labeled freed mem, report unsafe
695 else if (as.isFreedMem(addr))
696 return false;
697 }
698
699
700 return true;
701}
buffer offset
Definition cJSON.cpp:1113
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:108
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
static AbstractInterpretation & getAEInstance()
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
Set< const CallICFGNode * > checkpoints
static bool isNullMem(u32_t addr)
static bool isInvalidMem(u32_t addr)
const ICFGNode * getICFGNode() const
Get the ICFGNode related to the creation of this object.
bool isConstantByteSize() const
Check if byte size is a const value.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
IntervalValue getAccessOffset(AbstractState &as, NodeID objId, const GepStmt *gep)
Retrieves the access offset for a given object and GEP statement.
void addToGepObjOffsetFromBase(const GepObjVar *obj, const IntervalValue &offset)
Adds an offset to a GEP object.
Definition AEDetector.h:193
Map< std::string, std::vector< std::pair< u32_t, u32_t > > > extAPIBufOverflowCheckRules
Rules for checking buffer overflows in external APIs.
Definition AEDetector.h:321
void detect(AbstractState &as, const ICFGNode *)
Detect buffer overflow issues within a node.
bool detectStrcpy(AbstractState &as, const CallICFGNode *call)
Detects buffer overflow in 'strcpy' function calls.
bool detectStrcat(AbstractState &as, const CallICFGNode *call)
Detects buffer overflow in 'strcat' function calls.
IntervalValue getGepObjOffsetFromBase(const GepObjVar *obj) const
Retrieves the offset of a GEP object from its base.
Definition AEDetector.h:213
void handleStubFunctions(const CallICFGNode *)
Handles external API calls related to buffer overflow detection.
bool hasGepObjOffsetFromBase(const GepObjVar *obj) const
Checks if a GEP object has an associated offset.
Definition AEDetector.h:203
bool canSafelyAccessMemory(AbstractState &as, const SVFVar *value, const IntervalValue &len)
Checks if memory can be safely accessed.
void initExtAPIBufOverflowCheckRules()
Initializes external API buffer overflow check rules.
void detectExtAPI(AbstractState &as, const CallICFGNode *call)
Handles external API calls related to buffer overflow detection.
void updateGepObjOffsetFromBase(AbstractState &as, AddressValue gepAddrs, AddressValue objAddrs, IntervalValue offset)
Updates the offset of a GEP object from its base.
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:235
const std::string toString() const override
Definition ICFG.cpp:139
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:494
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:512
u32_t arg_size() const
Definition ICFGNode.h:499
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:43
const std::vector< std::string > & getExtFuncAnnotations(const FunObjVar *fun)
Definition ExtAPI.cpp:199
NodeType * getGNode(NodeID id) const
Get a node.
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:117
static IntervalValue bottom()
Create the bottom IntervalValue [+inf, -inf].
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
bool canSafelyDerefPtr(AbstractState &as, const SVFVar *ptr)
bool isUninit(AbstractValue v)
Checks if an Abstract Value is uninitialized.
Definition AEDetector.h:360
void detect(AbstractState &as, const ICFGNode *node)
Detects nullptr dereferences issues within a node.
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:372
void handleStubFunctions(const CallICFGNode *call)
Handles external API calls related to nullptr dereferences.
void detectExtAPI(AbstractState &as, const CallICFGNode *call)
Handle external API calls related to nullptr dereferences.
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:423
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
NodeID getId() const
Get ID.
Definition SVFValue.h:158
virtual const std::string & getName() const
Definition SVFValue.h:184
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:55
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:78
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:47