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#include <algorithm>
34
35using namespace SVF;
47{
49 if (!SVFUtil::isa<CallICFGNode>(node))
50 {
51 // Handle non-call nodes by analyzing GEP instructions
52 for (const SVFStmt* stmt : node->getSVFStmts())
53 {
54 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
55 {
56 SVFIR* svfir = PAG::getPAG();
57
58 // Update the GEP object offset from its base
59 const AbstractValue& lhsVal = ae.getAbsValue(gep->getLHSVar(), node);
60 const AbstractValue& rhsVal = ae.getAbsValue(gep->getRHSVar(), node);
61 updateGepObjOffsetFromBase(node, lhsVal.getAddrs(), rhsVal.getAddrs(),
62 ae.getGepByteOffset(gep));
63
64 const AddressValue& objAddrs = rhsVal.getAddrs();
65 for (const auto& addr : objAddrs)
66 {
67 NodeID objId = ae.getAbsState(node).getIDFromAddr(addr);
68 u32_t size = 0;
69 u32_t lower = 0;
70 // like `int arr[10]` which has constant size before runtime
72 {
73 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
74 lower = size;
75 }
76 else
77 {
78 // like `int len = ***; int arr[len]`, whose size can only be known in runtime
80 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
81 {
82 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
83 {
84 const auto bounds = ae.getAllocaInstByteSize(addrStmt);
85 size = bounds.upperBound;
86 lower = bounds.lowerBound;
87 }
88 }
89 }
90
91 // Calculate access offset and check for potential overflow
92 IntervalValue accessOffset = getAccessOffset(objId, gep);
93 if (accessOffset.ub().getIntNumeral() >= size)
94 {
95 AEException bug(stmt->toString());
96 addBugToReporter(bug, stmt->getICFGNode(),
97 {size, lower, accessOffset});
98 }
99 }
100 }
101 }
102 }
103 else
104 {
105 // Handle call nodes by checking for external API calls
106 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
107 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
108 {
110 }
111 }
112}
113
114
123{
124 // get function name
125 std::string funcName = callNode->getCalledFunction()->getName();
127 if (funcName == "SAFE_BUFACCESS")
128 {
129 ae.getUtils()->checkpoints.erase(callNode);
130 if (callNode->arg_size() < 2)
131 return;
132 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
133 if (val.isBottom())
134 {
135 val = IntervalValue(0);
136 assert(false && "SAFE_BUFACCESS size is bottom");
137 }
138 const ValVar* arg0Val = callNode->getArgument(0);
140 if (isSafe)
141 {
142 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe buffer access at SAFE_BUFACCESS")
143 << " — " << callNode->toString() << "\n";
144 return;
145 }
146 else
147 {
148 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected buffer overflow at SAFE_BUFACCESS")
149 << " — Position: " << callNode->getSourceLoc() << "\n";
150 assert(false);
151 }
152 }
153 else if (funcName == "UNSAFE_BUFACCESS")
154 {
155 ae.getUtils()->checkpoints.erase(callNode);
156 if (callNode->arg_size() < 2) return;
157 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
158 if (val.isBottom())
159 {
160 assert(false && "UNSAFE_BUFACCESS size is bottom");
161 }
162 const ValVar* arg0Val = callNode->getArgument(0);
164 if (!isSafe)
165 {
166 SVFUtil::outs() << SVFUtil::sucMsg("success: expected buffer overflow at UNSAFE_BUFACCESS")
167 << " — " << callNode->toString() << "\n";
168 return;
169 }
170 else
171 {
172 SVFUtil::outs() << SVFUtil::errMsg("failure: buffer overflow expected at UNSAFE_BUFACCESS, but none detected")
173 << " — Position: " << callNode->getSourceLoc() << "\n";
174 assert(false);
175 }
176 }
177}
178
186{
187 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
188 extAPIBufOverflowCheckRules["llvm_memcpy_p0_p0_i64"] = {{0, 2}, {1, 2}};
189 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
190 extAPIBufOverflowCheckRules["llvm_memcpy"] = {{0, 2}, {1, 2}};
191 extAPIBufOverflowCheckRules["llvm_memmove"] = {{0, 2}, {1, 2}};
192 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
193 extAPIBufOverflowCheckRules["llvm_memmove_p0_p0_i64"] = {{0, 2}, {1, 2}};
194 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
195 extAPIBufOverflowCheckRules["__memcpy_chk"] = {{0, 2}, {1, 2}};
196 extAPIBufOverflowCheckRules["memmove"] = {{0, 2}, {1, 2}};
197 extAPIBufOverflowCheckRules["bcopy"] = {{0, 2}, {1, 2}};
198 extAPIBufOverflowCheckRules["memccpy"] = {{0, 3}, {1, 3}};
199 extAPIBufOverflowCheckRules["__memmove_chk"] = {{0, 2}, {1, 2}};
200 extAPIBufOverflowCheckRules["llvm_memset"] = {{0, 2}};
201 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i32"] = {{0, 2}};
202 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i64"] = {{0, 2}};
203 extAPIBufOverflowCheckRules["llvm_memset_p0_i64"] = {{0, 2}};
204 extAPIBufOverflowCheckRules["__memset_chk"] = {{0, 2}};
205 extAPIBufOverflowCheckRules["wmemset"] = {{0, 2}};
206 extAPIBufOverflowCheckRules["strncpy"] = {{0, 2}, {1, 2}};
207 extAPIBufOverflowCheckRules["iconv"] = {{1, 2}, {3, 4}};
208}
209
219{
220 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
241 {
242 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
243 {
244 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
245 return;
246 }
247 std::vector<std::pair<u32_t, u32_t>> args =
249 for (auto arg : args)
250 {
251 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
252 const ValVar* argVar = call->getArgument(arg.first);
254 {
255 AEException bug(call->toString());
256 addBugToReporter(bug, call, info);
257 }
258 }
259 }
260 else if (extType == AbsExtAPI::MEMSET)
261 {
262 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
263 {
264 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
265 return;
266 }
267 std::vector<std::pair<u32_t, u32_t>> args =
269 for (auto arg : args)
270 {
271 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
272 const ValVar* argVar = call->getArgument(arg.first);
274 {
275 AEException bug(call->toString());
276 addBugToReporter(bug, call, info);
277 }
278 }
279 }
280 else if (extType == AbsExtAPI::STRCPY)
281 {
282 if (!detectStrcpy(call, info))
283 {
284 AEException bug(call->toString());
285 addBugToReporter(bug, call, info);
286 }
287 }
288 else if (extType == AbsExtAPI::STRCAT)
289 {
290 if (!detectStrcat(call, info))
291 {
292 AEException bug(call->toString());
293 addBugToReporter(bug, call, info);
294 }
295 }
296 else
297 {
298 // Handle other cases
299 }
300}
301
313{
314 SVFIR* svfir = PAG::getPAG();
316 auto obj = svfir->getSVFVar(objId);
317
318 if (SVFUtil::isa<BaseObjVar>(obj))
319 {
320 return ae.getGepByteOffset(gep);
321 }
322 else if (SVFUtil::isa<GepObjVar>(obj))
323 {
324 return getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(obj)) + ae.getGepByteOffset(gep);
325 }
326 else
327 {
328 assert(SVFUtil::isa<DummyObjVar>(obj) && "Unknown object type");
329 return IntervalValue::top();
330 }
331}
332
344{
345 SVFIR* svfir = PAG::getPAG();
347 const AbstractState& as = ae.getAbsState(node);
348
349 for (const auto& objAddr : objAddrs)
350 {
352 auto obj = svfir->getSVFVar(objId);
353
354 if (SVFUtil::isa<BaseObjVar>(obj))
355 {
356 // if the object is a BaseObjVar, add the offset directly
357 // like llvm bc `arr = alloc i8 12; p = gep arr, 4`
358 // we write key value pair {gep, 4}
359 for (const auto& gepAddr : gepAddrs)
360 {
361 NodeID gepObj = as.getIDFromAddr(gepAddr);
362 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getSVFVar(gepObj)))
363 {
365 }
366 else
367 {
369 "GEP object is neither a GepObjVar nor an address without a backing object");
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->getSVFVar(gepObj)))
383 {
385 {
391 }
392 else
393 {
394 assert(false &&
395 "GEP RHS object has no offset from base");
396 }
397 }
398 else
399 {
401 "GEP object is neither a GepObjVar nor an address without a backing object");
402 }
403 }
404 }
405 }
406}
407
419{
420 const ValVar* arg0Val = call->getArgument(0);
421 const ValVar* arg1Val = call->getArgument(1);
423 IntervalValue strLen = ae.getUtils()->getStrlen(arg1Val, call);
424 return canSafelyAccessMemory(arg0Val, strLen, call, &info);
425}
426
428{
430 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
431 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
432
433 if (std::find(strcatGroup.begin(), strcatGroup.end(), call->getCalledFunction()->getName()) != strcatGroup.end())
434 {
435 const ValVar* arg0Val = call->getArgument(0);
436 const ValVar* arg1Val = call->getArgument(1);
437 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
438 IntervalValue strLen1 = ae.getUtils()->getStrlen(arg1Val, call);
441 }
442 else if (std::find(strncatGroup.begin(), strncatGroup.end(), call->getCalledFunction()->getName()) != strncatGroup.end())
443 {
444 const ValVar* arg0Val = call->getArgument(0);
445 const ValVar* arg2Val = call->getArgument(2);
446 IntervalValue arg2Num = ae.getAbsValue(arg2Val, call).getInterval();
447 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
450 }
451 else
452 {
453 assert(false && "Unknown strcat function, please add it to strcatGroup or strncatGroup");
454 abort();
455 }
456}
457
470 const ICFGNode* node, BufferOverflowInfo* info)
471{
472 if (info) *info = {};
473 SVFIR* svfir = PAG::getPAG();
475
476 AbstractValue ptrVal = ae.getAbsValue(value, node);
477 if (!ptrVal.isAddr())
478 {
480 ae.updateAbsValue(value, ptrVal, node);
481 }
482
483 const AddressValue& addresses = ptrVal.getAddrs();
484 if (std::any_of(addresses.begin(), addresses.end(),
486 return false;
487
488 for (const auto& addr : addresses)
489 {
490 NodeID objId = ae.getAbsState(node).getIDFromAddr(addr);
491 u32_t size = 0;
492 u32_t lower = 0;
493 // if the object is a constant size object, get the size directly
495 {
496 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
497 lower = size;
498 }
499 else
500 {
501 // if the object is not a constant size object, get the size from the addrStmt
502 const ICFGNode* addrNode = svfir->getBaseObject(objId)->getICFGNode();
503 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
504 {
505 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
506 {
507 const auto bounds = ae.getAllocaInstByteSize(addrStmt);
508 size = bounds.upperBound;
509 lower = bounds.lowerBound;
510 }
511 }
512 }
513
515 // if the object is a GepObjVar, get the offset from the base object
516 if (SVFUtil::isa<GepObjVar>(svfir->getSVFVar(objId)))
517 {
518 offset = getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(svfir->getSVFVar(objId))) + len;
519 }
520 else if (SVFUtil::isa<BaseObjVar>(svfir->getSVFVar(objId)))
521 {
522 // if the object is a BaseObjVar, get the offset directly
523 offset = len;
524 }
525
526 // if the offset is greater than the size, return false
527 if (offset.ub().getIntNumeral() >= size)
528 {
529 if (info) *info = {size, lower, offset};
530 return false;
531 }
532 }
533 return true;
534}
535
537{
538 if (SVFUtil::isa<CallICFGNode>(node))
539 {
540 // external API like memset(*dst, elem, sz)
541 // we check if it's external api and check the corrisponding index
542 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
543 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
544 {
546 }
547 }
548 else
549 {
550 for (const auto& stmt: node->getSVFStmts())
551 {
552 if (const GepStmt* gep = SVFUtil::dyn_cast<GepStmt>(stmt))
553 {
554 // like llvm bitcode `p = gep p, idx`
555 // we check rhs p's all address are valid mem
556 const ValVar* rhs = gep->getRHSVar();
557 if (!canSafelyDerefPtr(rhs, node))
558 {
559 AEException bug(stmt->toString());
560 addBugToReporter(bug, stmt->getICFGNode());
561 }
562 }
563 else if (const LoadStmt* load = SVFUtil::dyn_cast<LoadStmt>(stmt))
564 {
565 // like llvm bitcode `p = load q`
566 // we check lhs p's all address are valid mem
567 const ValVar* lhs = load->getLHSVar();
568 if (!canSafelyDerefPtr(lhs, node))
569 {
570 AEException bug(stmt->toString());
571 addBugToReporter(bug, stmt->getICFGNode());
572 }
573 }
574 }
575 }
576}
577
578
580{
581 std::string funcName = callNode->getCalledFunction()->getName();
583 if (funcName == "UNSAFE_LOAD")
584 {
585 // void UNSAFE_LOAD(void* ptr);
586 ae.getUtils()->checkpoints.erase(callNode);
587 if (callNode->arg_size() < 1)
588 return;
589
590 const ValVar* arg0Val = callNode->getArgument(0);
591 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)
593 SVFUtil::outs() << "[UNSAFE_LOAD] node=" << callNode->getId()
594 << " arg0=" << arg0Val->getId() << " isSafe=" << isSafe
595 << "\n";
596 if (!isSafe)
597 {
598 SVFUtil::outs() << SVFUtil::sucMsg("success: expected null dereference at UNSAFE_LOAD")
599 << " — " << callNode->toString() << "\n";
600 return;
601 }
602 else
603 {
604 SVFUtil::outs() << SVFUtil::errMsg("failure: null dereference expected at UNSAFE_LOAD, but none detected")
605 << " — Position: " << callNode->getSourceLoc() << "\n";
606 assert(false);
607 }
608 }
609 else if (funcName == "SAFE_LOAD")
610 {
611 // void SAFE_LOAD(void* ptr);
612 ae.getUtils()->checkpoints.erase(callNode);
613 if (callNode->arg_size() < 1) return;
614 const ValVar* arg0Val = callNode->getArgument(0);
615 // opt may directly dereference a null pointer and call UNSAFE_LOAD(null)ols
617 if (isSafe)
618 {
619 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe dereference at SAFE_LOAD")
620 << " — " << callNode->toString() << "\n";
621 return;
622 }
623 else
624 {
625 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected null dereference at SAFE_LOAD")
626 << " — Position: " << callNode->getSourceLoc() << "\n";
627 assert(false);
628 }
629 }
630}
631
633{
634 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
635 // get ext type
636 // get argument index which are nullptr deref checkpoints for extapi
637 std::vector<u32_t> tmp_args;
638 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
639 {
640 if (annotation.find("MEMCPY") != std::string::npos)
641 {
642 if (call->arg_size() < 4)
643 {
644 // for memcpy(void* dest, const void* src, size_t n)
645 tmp_args.push_back(0);
646 tmp_args.push_back(1);
647 }
648 else
649 {
650 // for unsigned long iconv(void* cd, char **restrict inbuf, unsigned long *restrict inbytesleft, char **restrict outbuf, unsigned long *restrict outbytesleft)
651 tmp_args.push_back(1);
652 tmp_args.push_back(2);
653 tmp_args.push_back(3);
654 tmp_args.push_back(4);
655 }
656 }
657 else if (annotation.find("MEMSET") != std::string::npos)
658 {
659 // for memset(void* dest, elem, sz)
660 tmp_args.push_back(0);
661 }
662 else if (annotation.find("STRCPY") != std::string::npos)
663 {
664 // for strcpy(void* dest, void* src)
665 tmp_args.push_back(0);
666 tmp_args.push_back(1);
667 }
668 else if (annotation.find("STRCAT") != std::string::npos)
669 {
670 // for strcat(void* dest, const void* src)
671 // for strncat(void* dest, const void* src, size_t n)
672 tmp_args.push_back(0);
673 tmp_args.push_back(1);
674 }
675 }
676
677 for (const auto &arg: tmp_args)
678 {
679 if (call->arg_size() <= arg)
680 continue;
681 const ValVar* argVal = call->getArgument(arg);
682 if (argVal && !canSafelyDerefPtr(argVal, call))
683 {
684 AEException bug(call->toString());
685 addBugToReporter(bug, call);
686 }
687 }
688}
689
690
692{
694 const AbstractValue& AbsVal = ae.getAbsValue(value, node);
695 if (isUninit(AbsVal)) return false;
696 if (!AbsVal.isAddr()) return true;
697 for (const auto &addr: AbsVal.getAddrs())
698 {
699 // Unknown, null, and freed addresses cannot be safely dereferenced.
701 ae.getAbsState(node).isFreedMem(addr))
702 return false;
703 }
704 return true;
705}
#define BlackHoleObjAddr
buffer offset
Definition cJSON.cpp:1113
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:112
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:55
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 isNullOrBlackHoleAddr(u32_t addr)
Whether addr has no concrete backing memory object.
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.
s64_t getIntNumeral() const
bool detectStrcat(const CallICFGNode *call, BufferOverflowInfo &info)
Detects buffer overflow in 'strcat' function calls.
void addToGepObjOffsetFromBase(const GepObjVar *obj, const IntervalValue &offset)
Adds an offset to a GEP object.
Definition AEDetector.h:204
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:343
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.
IntervalValue getGepObjOffsetFromBase(const GepObjVar *obj) const
Retrieves the offset of a GEP object from its base.
Definition AEDetector.h:224
bool canSafelyAccessMemory(const ValVar *value, const IntervalValue &len, const ICFGNode *node, BufferOverflowInfo *info=nullptr)
Checks if memory can be safely accessed.
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:214
void initExtAPIBufOverflowCheckRules()
Initializes external API buffer overflow check rules.
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:249
bool detectStrcpy(const CallICFGNode *call, BufferOverflowInfo &info)
Detects buffer overflow in 'strcpy' function calls.
const std::string toString() const override
Definition ICFG.cpp:129
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:483
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:501
u32_t arg_size() const
Definition ICFGNode.h:488
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:43
const std::vector< std::string > & getExtFuncAnnotations(const FunObjVar *fun)
Definition ExtAPI.cpp:232
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:116
const BoundedInt & ub() const
Return the upper bound.
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:382
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:394
void detectExtAPI(const CallICFGNode *call)
Handle external API calls related to nullptr dereferences.
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:499
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:136
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:121
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:75
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
Definition SVFUtil.cpp:98
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:526
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:76
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
unsigned u32_t
Definition GeneralType.h:67