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 on: May 1, 2025
26// Author: Xiao Cheng, Jiawei Wang, Mingxiu Wang
27//
28
30#include <AE/Svfexe/AbsExtAPI.h>
33
34using namespace SVF;
46{
48 if (!SVFUtil::isa<CallICFGNode>(node))
49 {
50 // Handle non-call nodes by analyzing GEP instructions
51 for (const SVFStmt* stmt : node->getSVFStmts())
52 {
53 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
54 {
55 SVFIR* svfir = PAG::getPAG();
56
57 // Update the GEP object offset from its base
58 const AbstractValue& lhsVal = ae.getAbsValue(gep->getLHSVar(), node);
59 const AbstractValue& rhsVal = ae.getAbsValue(gep->getRHSVar(), node);
60 updateGepObjOffsetFromBase(node, lhsVal.getAddrs(), rhsVal.getAddrs(),
61 ae.getStateMgr()->getGepByteOffset(gep));
62
63 const AddressValue& objAddrs = rhsVal.getAddrs();
64 for (const auto& addr : objAddrs)
65 {
66 NodeID objId = ae.getAbsState(node).getIDFromAddr(addr);
67 u32_t size = 0;
68 // like `int arr[10]` which has constant size before runtime
70 {
71 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
72 }
73 else
74 {
75 // like `int len = ***; int arr[len]`, whose size can only be known in runtime
77 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
78 {
79 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
80 {
81 size = ae.getStateMgr()->getAllocaInstByteSize(addrStmt);
82 }
83 }
84 }
85
86 // Calculate access offset and check for potential overflow
88 if (accessOffset.ub().getIntNumeral() >= size)
89 {
90 AEException bug(stmt->toString());
91 addBugToReporter(bug, stmt->getICFGNode());
92 }
93 }
94 }
95 }
96 }
97 else
98 {
99 // Handle call nodes by checking for external API calls
100 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
101 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
102 {
104 }
105 }
106}
107
108
117{
118 // get function name
119 std::string funcName = callNode->getCalledFunction()->getName();
121 if (funcName == "SAFE_BUFACCESS")
122 {
123 ae.getUtils()->checkpoints.erase(callNode);
124 if (callNode->arg_size() < 2)
125 return;
126 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
127 if (val.isBottom())
128 {
129 val = IntervalValue(0);
130 assert(false && "SAFE_BUFACCESS size is bottom");
131 }
132 const ValVar* arg0Val = callNode->getArgument(0);
134 if (isSafe)
135 {
136 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe buffer access at SAFE_BUFACCESS")
137 << " — " << callNode->toString() << "\n";
138 return;
139 }
140 else
141 {
142 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected buffer overflow at SAFE_BUFACCESS")
143 << " — Position: " << callNode->getSourceLoc() << "\n";
144 assert(false);
145 }
146 }
147 else if (funcName == "UNSAFE_BUFACCESS")
148 {
149 ae.getUtils()->checkpoints.erase(callNode);
150 if (callNode->arg_size() < 2) return;
151 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
152 if (val.isBottom())
153 {
154 assert(false && "UNSAFE_BUFACCESS size is bottom");
155 }
156 const ValVar* arg0Val = callNode->getArgument(0);
158 if (!isSafe)
159 {
160 SVFUtil::outs() << SVFUtil::sucMsg("success: expected buffer overflow at UNSAFE_BUFACCESS")
161 << " — " << callNode->toString() << "\n";
162 return;
163 }
164 else
165 {
166 SVFUtil::outs() << SVFUtil::errMsg("failure: buffer overflow expected at UNSAFE_BUFACCESS, but none detected")
167 << " — Position: " << callNode->getSourceLoc() << "\n";
168 assert(false);
169 }
170 }
171}
172
180{
181 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
182 extAPIBufOverflowCheckRules["llvm_memcpy_p0_p0_i64"] = {{0, 2}, {1, 2}};
183 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
184 extAPIBufOverflowCheckRules["llvm_memcpy"] = {{0, 2}, {1, 2}};
185 extAPIBufOverflowCheckRules["llvm_memmove"] = {{0, 2}, {1, 2}};
186 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
187 extAPIBufOverflowCheckRules["llvm_memmove_p0_p0_i64"] = {{0, 2}, {1, 2}};
188 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
189 extAPIBufOverflowCheckRules["__memcpy_chk"] = {{0, 2}, {1, 2}};
190 extAPIBufOverflowCheckRules["memmove"] = {{0, 2}, {1, 2}};
191 extAPIBufOverflowCheckRules["bcopy"] = {{0, 2}, {1, 2}};
192 extAPIBufOverflowCheckRules["memccpy"] = {{0, 3}, {1, 3}};
193 extAPIBufOverflowCheckRules["__memmove_chk"] = {{0, 2}, {1, 2}};
194 extAPIBufOverflowCheckRules["llvm_memset"] = {{0, 2}};
195 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i32"] = {{0, 2}};
196 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i64"] = {{0, 2}};
197 extAPIBufOverflowCheckRules["llvm_memset_p0_i64"] = {{0, 2}};
198 extAPIBufOverflowCheckRules["__memset_chk"] = {{0, 2}};
199 extAPIBufOverflowCheckRules["wmemset"] = {{0, 2}};
200 extAPIBufOverflowCheckRules["strncpy"] = {{0, 2}, {1, 2}};
201 extAPIBufOverflowCheckRules["iconv"] = {{1, 2}, {3, 4}};
202}
203
213{
214 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
216
218
219 // Determine the type of external memory API
220 for (const std::string &annotation : ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
221 {
222 if (annotation.find("MEMCPY") != std::string::npos)
224 if (annotation.find("MEMSET") != std::string::npos)
226 if (annotation.find("STRCPY") != std::string::npos)
228 if (annotation.find("STRCAT") != std::string::npos)
230 }
231
232 // Apply buffer overflow checks based on the determined API type
234 {
235 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
236 {
237 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
238 return;
239 }
240 std::vector<std::pair<u32_t, u32_t>> args =
242 for (auto arg : args)
243 {
244 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
245 const ValVar* argVar = call->getArgument(arg.first);
247 {
248 AEException bug(call->toString());
249 addBugToReporter(bug, call);
250 }
251 }
252 }
253 else if (extType == AbsExtAPI::MEMSET)
254 {
255 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
256 {
257 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
258 return;
259 }
260 std::vector<std::pair<u32_t, u32_t>> args =
262 for (auto arg : args)
263 {
264 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
265 const ValVar* argVar = call->getArgument(arg.first);
267 {
268 AEException bug(call->toString());
269 addBugToReporter(bug, call);
270 }
271 }
272 }
273 else if (extType == AbsExtAPI::STRCPY)
274 {
275 if (!detectStrcpy(call))
276 {
277 AEException bug(call->toString());
278 addBugToReporter(bug, call);
279 }
280 }
281 else if (extType == AbsExtAPI::STRCAT)
282 {
283 if (!detectStrcat(call))
284 {
285 AEException bug(call->toString());
286 addBugToReporter(bug, call);
287 }
288 }
289 else
290 {
291 // Handle other cases
292 }
293}
294
306{
307 SVFIR* svfir = PAG::getPAG();
309 auto obj = svfir->getSVFVar(objId);
310
311 if (SVFUtil::isa<BaseObjVar>(obj))
312 {
313 return ae.getStateMgr()->getGepByteOffset(gep);
314 }
315 else if (SVFUtil::isa<GepObjVar>(obj))
316 {
317 return getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(obj)) + ae.getStateMgr()->getGepByteOffset(gep);
318 }
319 else
320 {
321 assert(SVFUtil::isa<DummyObjVar>(obj) && "Unknown object type");
322 return IntervalValue::top();
323 }
324}
325
337{
338 SVFIR* svfir = PAG::getPAG();
340 const AbstractState& as = ae.getAbsState(node);
341
342 for (const auto& objAddr : objAddrs)
343 {
345 auto obj = svfir->getSVFVar(objId);
346
347 if (SVFUtil::isa<BaseObjVar>(obj))
348 {
349 // if the object is a BaseObjVar, add the offset directly
350 // like llvm bc `arr = alloc i8 12; p = gep arr, 4`
351 // we write key value pair {gep, 4}
352 for (const auto& gepAddr : gepAddrs)
353 {
354 NodeID gepObj = as.getIDFromAddr(gepAddr);
355 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getSVFVar(gepObj)))
356 {
358 }
359 else
360 {
361 assert(AbstractState::isBlackHoleObjAddr(gepAddr) && "GEP object is neither a GepObjVar nor an invalid memory address");
362 }
363 }
364 }
365 else if (SVFUtil::isa<GepObjVar>(obj))
366 {
367 // if the object is a GepObjVar, add the offset from the base object
368 // like llvm bc `arr = alloc i8 12; p = gep arr, 4; q = gep p, 6`
369 // we retreive {p, 4} and write {q, 4+6}
370 const GepObjVar* objVar = SVFUtil::cast<GepObjVar>(obj);
371 for (const auto& gepAddr : gepAddrs)
372 {
373 NodeID gepObj = as.getIDFromAddr(gepAddr);
374 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getSVFVar(gepObj)))
375 {
377 {
383 }
384 else
385 {
386 assert(false &&
387 "GEP RHS object has no offset from base");
388 }
389 }
390 else
391 {
392 assert(AbstractState::isBlackHoleObjAddr(gepAddr) && "GEP object is neither a GepObjVar nor an invalid memory address");
393 }
394 }
395 }
396 }
397}
398
410{
411 const ValVar* arg0Val = call->getArgument(0);
412 const ValVar* arg1Val = call->getArgument(1);
414 IntervalValue strLen = ae.getUtils()->getStrlen(arg1Val, call);
415 return canSafelyAccessMemory(arg0Val, strLen, call);
416}
417
419{
421 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
422 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
423
424 if (std::find(strcatGroup.begin(), strcatGroup.end(), call->getCalledFunction()->getName()) != strcatGroup.end())
425 {
426 const ValVar* arg0Val = call->getArgument(0);
427 const ValVar* arg1Val = call->getArgument(1);
428 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
429 IntervalValue strLen1 = ae.getUtils()->getStrlen(arg1Val, call);
432 }
433 else if (std::find(strncatGroup.begin(), strncatGroup.end(), call->getCalledFunction()->getName()) != strncatGroup.end())
434 {
435 const ValVar* arg0Val = call->getArgument(0);
436 const ValVar* arg2Val = call->getArgument(2);
437 IntervalValue arg2Num = ae.getAbsValue(arg2Val, call).getInterval();
438 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
441 }
442 else
443 {
444 assert(false && "Unknown strcat function, please add it to strcatGroup or strncatGroup");
445 abort();
446 }
447}
448
461{
462 SVFIR* svfir = PAG::getPAG();
464
465 AbstractValue ptrVal = ae.getAbsValue(value, node);
466 if (!ptrVal.isAddr())
467 {
469 ae.updateAbsValue(value, ptrVal, node);
470 }
471 for (const auto& addr : ptrVal.getAddrs())
472 {
473 NodeID objId = ae.getAbsState(node).getIDFromAddr(addr);
474 u32_t size = 0;
475 // if the object is a constant size object, get the size directly
477 {
478 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
479 }
480 else
481 {
482 // if the object is not a constant size object, get the size from the addrStmt
483 const ICFGNode* addrNode = svfir->getBaseObject(objId)->getICFGNode();
484 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
485 {
486 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
487 {
488 size = ae.getStateMgr()->getAllocaInstByteSize(addrStmt);
489 }
490 }
491 }
492
494 // if the object is a GepObjVar, get the offset from the base object
495 if (SVFUtil::isa<GepObjVar>(svfir->getSVFVar(objId)))
496 {
497 offset = getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(svfir->getSVFVar(objId))) + len;
498 }
499 else if (SVFUtil::isa<BaseObjVar>(svfir->getSVFVar(objId)))
500 {
501 // if the object is a BaseObjVar, get the offset directly
502 offset = len;
503 }
504
505 // if the offset is greater than the size, return false
506 if (offset.ub().getIntNumeral() >= size)
507 {
508 return false;
509 }
510 }
511 return true;
512}
513
515{
516 if (SVFUtil::isa<CallICFGNode>(node))
517 {
518 // external API like memset(*dst, elem, sz)
519 // we check if it's external api and check the corrisponding index
520 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
521 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
522 {
524 }
525 }
526 else
527 {
528 for (const auto& stmt: node->getSVFStmts())
529 {
530 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
531 {
532 // like llvm bitcode `p = gep p, idx`
533 // we check rhs p's all address are valid mem
534 const ValVar* rhs = gep->getRHSVar();
535 if (!canSafelyDerefPtr(rhs, node))
536 {
537 AEException bug(stmt->toString());
538 addBugToReporter(bug, stmt->getICFGNode());
539 }
540 }
541 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
542 {
543 // like llvm bitcode `p = load q`
544 // we check lhs p's all address are valid mem
545 const ValVar* lhs = load->getLHSVar();
546 if (!canSafelyDerefPtr(lhs, node))
547 {
548 AEException bug(stmt->toString());
549 addBugToReporter(bug, stmt->getICFGNode());
550 }
551 }
552 }
553 }
554}
555
556
558{
559 std::string funcName = callNode->getCalledFunction()->getName();
561 if (funcName == "UNSAFE_LOAD")
562 {
563 // void UNSAFE_LOAD(void* ptr);
564 ae.getUtils()->checkpoints.erase(callNode);
565 if (callNode->arg_size() < 1)
566 return;
567
568 const ValVar* arg0Val = callNode->getArgument(0);
569 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)
571 if (!isSafe)
572 {
573 SVFUtil::outs() << SVFUtil::sucMsg("success: expected null dereference at UNSAFE_LOAD")
574 << " — " << callNode->toString() << "\n";
575 return;
576 }
577 else
578 {
579 SVFUtil::outs() << SVFUtil::errMsg("failure: null dereference expected at UNSAFE_LOAD, but none detected")
580 << " — Position: " << callNode->getSourceLoc() << "\n";
581 assert(false);
582 }
583 }
584 else if (funcName == "SAFE_LOAD")
585 {
586 // void SAFE_LOAD(void* ptr);
587 ae.getUtils()->checkpoints.erase(callNode);
588 if (callNode->arg_size() < 1) return;
589 const ValVar* arg0Val = callNode->getArgument(0);
590 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)ols
592 if (isSafe)
593 {
594 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe dereference at SAFE_LOAD")
595 << " — " << callNode->toString() << "\n";
596 return;
597 }
598 else
599 {
600 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected null dereference at SAFE_LOAD")
601 << " — Position: " << callNode->getSourceLoc() << "\n";
602 assert(false);
603 }
604 }
605}
606
608{
609 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
610 // get ext type
611 // get argument index which are nullptr deref checkpoints for extapi
612 std::vector<u32_t> tmp_args;
613 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
614 {
615 if (annotation.find("MEMCPY") != std::string::npos)
616 {
617 if (call->arg_size() < 4)
618 {
619 // for memcpy(void* dest, const void* src, size_t n)
620 tmp_args.push_back(0);
621 tmp_args.push_back(1);
622 }
623 else
624 {
625 // for unsigned long iconv(void* cd, char **restrict inbuf, unsigned long *restrict inbytesleft, char **restrict outbuf, unsigned long *restrict outbytesleft)
626 tmp_args.push_back(1);
627 tmp_args.push_back(2);
628 tmp_args.push_back(3);
629 tmp_args.push_back(4);
630 }
631 }
632 else if (annotation.find("MEMSET") != std::string::npos)
633 {
634 // for memset(void* dest, elem, sz)
635 tmp_args.push_back(0);
636 }
637 else if (annotation.find("STRCPY") != std::string::npos)
638 {
639 // for strcpy(void* dest, void* src)
640 tmp_args.push_back(0);
641 tmp_args.push_back(1);
642 }
643 else if (annotation.find("STRCAT") != std::string::npos)
644 {
645 // for strcat(void* dest, const void* src)
646 // for strncat(void* dest, const void* src, size_t n)
647 tmp_args.push_back(0);
648 tmp_args.push_back(1);
649 }
650 }
651
652 for (const auto &arg: tmp_args)
653 {
654 if (call->arg_size() <= arg)
655 continue;
656 const ValVar* argVal = call->getArgument(arg);
657 if (argVal && !canSafelyDerefPtr(argVal, call))
658 {
659 AEException bug(call->toString());
660 addBugToReporter(bug, call);
661 }
662 }
663}
664
665
667{
669 const AbstractValue& AbsVal = ae.getAbsValue(value, node);
670 // uninit value cannot be dereferenced, return unsafe
671 if (isUninit(AbsVal)) return false;
672 // Interval Value (non-addr) is not the checkpoint of nullptr dereference, return safe
673 if (!AbsVal.isAddr()) return true;
674 for (const auto &addr: AbsVal.getAddrs())
675 {
676 // if the addr itself is invalid mem, report unsafe
678 return false;
679 // if nullptr is detected, return unsafe
681 return false;
682 // if addr is labeled freed mem, report unsafe
683 else if (ae.getAbsState(node).isFreedMem(addr))
684 return false;
685 }
686 return true;
687}
#define BlackHoleObjAddr
buffer offset
Definition cJSON.cpp:1113
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:113
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
static AbstractInterpretation & getAEInstance()
u32_t getIDFromAddr(u32_t addr) const
Return the internal index if addr is an address otherwise return the value of idx.
static bool isNullMem(u32_t addr)
static bool isBlackHoleObjAddr(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.
void addToGepObjOffsetFromBase(const GepObjVar *obj, const IntervalValue &offset)
Adds an offset to a GEP object.
Definition AEDetector.h:198
void detect(const ICFGNode *) override
Detect buffer overflow issues within a node.
Map< std::string, std::vector< std::pair< u32_t, u32_t > > > extAPIBufOverflowCheckRules
Rules for checking buffer overflows in external APIs.
Definition AEDetector.h:327
IntervalValue getAccessOffset(NodeID objId, const GepStmt *gep)
Retrieves the access offset for a given object and GEP statement.
void updateGepObjOffsetFromBase(const ICFGNode *node, AddressValue gepAddrs, AddressValue objAddrs, IntervalValue offset)
Updates the offset of a GEP object from its base.
void detectExtAPI(const CallICFGNode *call)
Handles external API calls related to buffer overflow detection.
bool canSafelyAccessMemory(const ValVar *value, const IntervalValue &len, const ICFGNode *node)
Checks if memory can be safely accessed.
IntervalValue getGepObjOffsetFromBase(const GepObjVar *obj) const
Retrieves the offset of a GEP object from its base.
Definition AEDetector.h:218
bool detectStrcpy(const CallICFGNode *call)
Detects buffer overflow in 'strcpy' function calls.
void handleStubFunctions(const CallICFGNode *) override
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:208
void initExtAPIBufOverflowCheckRules()
Initializes external API buffer overflow check rules.
bool detectStrcat(const CallICFGNode *call)
Detects buffer overflow in 'strcat' function calls.
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:243
const std::string toString() const override
Definition ICFG.cpp:128
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:482
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:500
u32_t arg_size() const
Definition ICFGNode.h:487
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:44
const std::vector< std::string > & getExtFuncAnnotations(const FunObjVar *fun)
Definition ExtAPI.cpp:256
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:115
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
bool canSafelyDerefPtr(const ValVar *ptr, const ICFGNode *node)
bool isUninit(AbstractValue v)
Checks if an Abstract Value is uninitialized.
Definition AEDetector.h:366
void handleStubFunctions(const CallICFGNode *call) override
Handles external API calls related to nullptr dereferences.
void detect(const ICFGNode *node) override
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:378
void detectExtAPI(const CallICFGNode *call)
Handle external API calls related to nullptr dereferences.
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:496
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:133
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:118
NodeID getId() const
Get ID.
Definition SVFValue.h:163
virtual const std::string & getName() const
Definition SVFValue.h:189
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:70
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:47