Static Value-Flow Analysis
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
SVF::BufOverflowDetector Class Reference

Detector for identifying buffer overflow issues. More...

#include <AEDetector.h>

Inheritance diagram for SVF::BufOverflowDetector:
SVF::AEDetector

Public Member Functions

 BufOverflowDetector ()
 Constructor initializes the detector kind to BUF_OVERFLOW and sets up external API buffer overflow rules.
 
 ~BufOverflowDetector ()=default
 Destructor.
 
void updateGepObjOffsetFromBase (const ICFGNode *node, AddressValue gepAddrs, AddressValue objAddrs, IntervalValue offset)
 Updates the offset of a GEP object from its base.
 
void detect (const ICFGNode *) override
 Detect buffer overflow issues within a node.
 
void handleStubFunctions (const CallICFGNode *) override
 Handles external API calls related to buffer overflow detection.
 
void addToGepObjOffsetFromBase (const GepObjVar *obj, const IntervalValue &offset)
 Adds an offset to a GEP object.
 
bool hasGepObjOffsetFromBase (const GepObjVar *obj) const
 Checks if a GEP object has an associated offset.
 
IntervalValue getGepObjOffsetFromBase (const GepObjVar *obj) const
 Retrieves the offset of a GEP object from its base.
 
IntervalValue getAccessOffset (NodeID objId, const GepStmt *gep)
 Retrieves the access offset for a given object and GEP statement.
 
void addBugToReporter (const AEException &e, const ICFGNode *node)
 Adds a bug to the reporter based on an exception.
 
void reportBug () override
 Reports all detected buffer overflow bugs.
 
void initExtAPIBufOverflowCheckRules ()
 Initializes external API buffer overflow check rules.
 
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.
 
- Public Member Functions inherited from SVF::AEDetector
 AEDetector ()
 Constructor initializes the detector kind to UNKNOWN.
 
virtual ~AEDetector ()=default
 Virtual destructor for safe polymorphic use.
 
DetectorKind getKind () const
 Get the kind of the detector.
 

Static Public Member Functions

static bool classof (const AEDetector *detector)
 Check if the detector is of the BUF_OVERFLOW kind.
 
- Static Public Member Functions inherited from SVF::AEDetector
static bool classof (const AEDetector *detector)
 Check if the detector is of the UNKNOWN kind.
 

Private Member Functions

bool detectStrcat (const CallICFGNode *call)
 Detects buffer overflow in 'strcat' function calls.
 
bool detectStrcpy (const CallICFGNode *call)
 Detects buffer overflow in 'strcpy' function calls.
 

Private Attributes

Map< const GepObjVar *, IntervalValue > gepObjOffsetFromBase
 Maps GEP objects to their offsets from the base.
 
Map< std::string, std::vector< std::pair< u32_t, u32_t > > > extAPIBufOverflowCheckRules
 Rules for checking buffer overflows in external APIs.
 
Set< std::string > bugLoc
 Set of locations where bugs have been reported.
 
SVFBugReport recoder
 Recorder for abstract execution bugs.
 
Map< const ICFGNode *, std::string > nodeToBugInfo
 Maps ICFG nodes to bug information.
 

Friends

class AbstractInterpretation
 

Additional Inherited Members

- Public Types inherited from SVF::AEDetector
enum  DetectorKind { BUF_OVERFLOW , NULL_DEREF , UNKNOWN }
 Enumerates the types of detectors available. More...
 
- Protected Attributes inherited from SVF::AEDetector
DetectorKind kind
 The kind of the detector.
 

Detailed Description

Detector for identifying buffer overflow issues.

Definition at line 138 of file AEDetector.h.

Constructor & Destructor Documentation

◆ BufOverflowDetector()

SVF::BufOverflowDetector::BufOverflowDetector ( )
inline

Constructor initializes the detector kind to BUF_OVERFLOW and sets up external API buffer overflow rules.

Definition at line 145 of file AEDetector.h.

146 {
149 }
@ BUF_OVERFLOW
Detector for buffer overflow issues.
Definition AEDetector.h:51
DetectorKind kind
The kind of the detector.
Definition AEDetector.h:104
void initExtAPIBufOverflowCheckRules()
Initializes external API buffer overflow check rules.

◆ ~BufOverflowDetector()

SVF::BufOverflowDetector::~BufOverflowDetector ( )
default

Destructor.

Member Function Documentation

◆ addBugToReporter()

void SVF::BufOverflowDetector::addBugToReporter ( const AEException &  e,
const ICFGNode *  node 
)
inline

Adds a bug to the reporter based on an exception.

Parameters
eThe exception that was thrown.
nodePointer to the ICFG node where the bug was detected.

Definition at line 242 of file AEDetector.h.

243 {
244
247 eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
248
249 if (eventStack.empty())
250 {
251 return; // If the event stack is empty, return early
252 }
253
254 std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
255
256 // Check if the bug at this location has already been reported
257 if (bugLoc.find(loc) != bugLoc.end())
258 {
259 return; // If the bug location is already reported, return early
260 }
261 else
262 {
263 bugLoc.insert(loc); // Otherwise, mark this location as reported
264 }
265
266 // Add the bug to the recorder with details from the event stack
268 nodeToBugInfo[node] = e.what(); // Record the exception information for the node
269 }
SVFBugReport recoder
Recorder for abstract execution bugs.
Definition AEDetector.h:328
Set< std::string > bugLoc
Set of locations where bugs have been reported.
Definition AEDetector.h:327
Map< const ICFGNode *, std::string > nodeToBugInfo
Maps ICFG nodes to bug information.
Definition AEDetector.h:329
std::vector< SVFBugEvent > EventStack
void addAbsExecBug(GenericBug::BugType bugType, const GenericBug::EventStack &eventStack, s64_t allocLowerBound, s64_t allocUpperBound, s64_t accessLowerBound, s64_t accessUpperBound)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76

◆ addToGepObjOffsetFromBase()

void SVF::BufOverflowDetector::addToGepObjOffsetFromBase ( const GepObjVar *  obj,
const IntervalValue &  offset 
)
inline

Adds an offset to a GEP object.

Parameters
objPointer to the GEP object.
offsetThe interval value of the offset.

Definition at line 197 of file AEDetector.h.

198 {
200 }
buffer offset
Definition cJSON.cpp:1113
Map< const GepObjVar *, IntervalValue > gepObjOffsetFromBase
Maps GEP objects to their offsets from the base.
Definition AEDetector.h:325

◆ canSafelyAccessMemory()

bool BufOverflowDetector::canSafelyAccessMemory ( const ValVar *  value,
const IntervalValue &  len,
const ICFGNode *  node 
)

Checks if memory can be safely accessed.

Checks if a memory access is safe given a specific buffer length.

Parameters
valuePointer to the SVF var.
lenThe interval value representing the length of the memory access.
nodeThe ICFG node providing context.
Returns
True if the memory access is safe, false otherwise.

This function ensures that a given memory access, starting at a specific value, does not exceed the allocated size of the buffer.

Parameters
asReference to the abstract state.
valuePointer to the SVF var.
lenThe interval value representing the length of the memory access.
Returns
True if the memory access is safe, false otherwise.

Definition at line 463 of file AEDetector.cpp.

464{
465 SVFIR* svfir = PAG::getPAG();
467
468 AbstractValue ptrVal = ae.getAbsValue(value, node);
469 if (!ptrVal.isAddr())
470 {
472 ae.updateAbsValue(value, ptrVal, node);
473 }
474
475 const AddressValue& addresses = ptrVal.getAddrs();
476 if (std::any_of(addresses.begin(), addresses.end(),
478 return false;
479
480 for (const auto& addr : addresses)
481 {
482 NodeID objId = ae.getAbsState(node).getIDFromAddr(addr);
483 u32_t size = 0;
484 // if the object is a constant size object, get the size directly
486 {
487 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
488 }
489 else
490 {
491 // if the object is not a constant size object, get the size from the addrStmt
492 const ICFGNode* addrNode = svfir->getBaseObject(objId)->getICFGNode();
493 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
494 {
495 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
496 {
497 size = ae.getAllocaInstByteSize(addrStmt);
498 }
499 }
500 }
501
503 // if the object is a GepObjVar, get the offset from the base object
504 if (SVFUtil::isa<GepObjVar>(svfir->getSVFVar(objId)))
505 {
506 offset = getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(svfir->getSVFVar(objId))) + len;
507 }
508 else if (SVFUtil::isa<BaseObjVar>(svfir->getSVFVar(objId)))
509 {
510 // if the object is a BaseObjVar, get the offset directly
511 offset = len;
512 }
513
514 // if the offset is greater than the size, return false
515 if (offset.ub().getIntNumeral() >= size)
516 {
517 return false;
518 }
519 }
520 return true;
521}
#define BlackHoleObjAddr
unsigned u32_t
Definition CommandLine.h:18
static AbstractInterpretation & getAEInstance()
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.
IntervalValue getGepObjOffsetFromBase(const GepObjVar *obj) const
Retrieves the offset of a GEP object from its base.
Definition AEDetector.h:217
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:498
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:135
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:120
u32_t NodeID
Definition GeneralType.h:76

◆ classof()

static bool SVF::BufOverflowDetector::classof ( const AEDetector *  detector)
inlinestatic

Check if the detector is of the BUF_OVERFLOW kind.

Parameters
detectorPointer to the detector.
Returns
True if the detector is of type BUF_OVERFLOW, false otherwise.

Definition at line 161 of file AEDetector.h.

162 {
163 return detector->getKind() == AEDetector::BUF_OVERFLOW;
164 }

◆ detect()

void BufOverflowDetector::detect ( const ICFGNode *  node)
overridevirtual

Detect buffer overflow issues within a node.

Detects buffer overflow issues within a given ICFG node.

Parameters
asReference to the abstract state.
nodePointer to the ICFG node.

This function handles both non-call nodes, where it analyzes GEP (GetElementPtr) instructions for potential buffer overflows, and call nodes, where it checks for external API calls that may cause overflows.

Parameters
asReference to the abstract state.
nodePointer to the ICFG node.

Implements SVF::AEDetector.

Definition at line 46 of file AEDetector.cpp.

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 // like `int arr[10]` which has constant size before runtime
71 {
72 size = svfir->getBaseObject(objId)->getByteSizeOfObj();
73 }
74 else
75 {
76 // like `int len = ***; int arr[len]`, whose size can only be known in runtime
78 for (const SVFStmt* stmt2 : addrNode->getSVFStmts())
79 {
80 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
81 {
82 size = ae.getAllocaInstByteSize(addrStmt);
83 }
84 }
85 }
86
87 // Calculate access offset and check for potential overflow
89 if (accessOffset.ub().getIntNumeral() >= size)
90 {
91 AEException bug(stmt->toString());
92 addBugToReporter(bug, stmt->getICFGNode());
93 }
94 }
95 }
96 }
97 }
98 else
99 {
100 // Handle call nodes by checking for external API calls
101 const CallICFGNode* callNode = SVFUtil::cast<CallICFGNode>(node);
102 if (SVFUtil::isExtCall(callNode->getCalledFunction()))
103 {
105 }
106 }
107}
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:112
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.
void addBugToReporter(const AEException &e, const ICFGNode *node)
Adds a bug to the reporter based on an exception.
Definition AEDetector.h:242
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:526

◆ detectExtAPI()

void BufOverflowDetector::detectExtAPI ( const CallICFGNode *  call)

Handles external API calls related to buffer overflow detection.

Parameters
asReference to the abstract state.
callPointer to the call ICFG node.

This function checks the type of external memory API (e.g., memcpy, memset, strcpy, strcat) and applies the corresponding buffer overflow checks based on predefined rules.

Parameters
callPointer to the call ICFG node.

Definition at line 213 of file AEDetector.cpp.

214{
215 assert(call->getCalledFunction() && "FunObjVar* is nullptr");
217
219
220 // Determine the type of external memory API
221 for (const std::string &annotation : ExtAPI::getExtAPI()->getExtFuncAnnotations(call->getCalledFunction()))
222 {
223 if (annotation.find("MEMCPY") != std::string::npos)
225 if (annotation.find("MEMSET") != std::string::npos)
227 if (annotation.find("STRCPY") != std::string::npos)
229 if (annotation.find("STRCAT") != std::string::npos)
231 }
232
233 // Apply buffer overflow checks based on the determined API type
235 {
236 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
237 {
238 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
239 return;
240 }
241 std::vector<std::pair<u32_t, u32_t>> args =
243 for (auto arg : args)
244 {
245 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
246 const ValVar* argVar = call->getArgument(arg.first);
248 {
249 AEException bug(call->toString());
250 addBugToReporter(bug, call);
251 }
252 }
253 }
254 else if (extType == AbsExtAPI::MEMSET)
255 {
256 if (extAPIBufOverflowCheckRules.count(call->getCalledFunction()->getName()) == 0)
257 {
258 SVFUtil::errs() << "Warning: " << call->getCalledFunction()->getName() << " is not in the rules, please implement it\n";
259 return;
260 }
261 std::vector<std::pair<u32_t, u32_t>> args =
263 for (auto arg : args)
264 {
265 IntervalValue offset = ae.getAbsValue(call->getArgument(arg.second), call).getInterval() - IntervalValue(1);
266 const ValVar* argVar = call->getArgument(arg.first);
268 {
269 AEException bug(call->toString());
270 addBugToReporter(bug, call);
271 }
272 }
273 }
274 else if (extType == AbsExtAPI::STRCPY)
275 {
276 if (!detectStrcpy(call))
277 {
278 AEException bug(call->toString());
279 addBugToReporter(bug, call);
280 }
281 }
282 else if (extType == AbsExtAPI::STRCAT)
283 {
284 if (!detectStrcat(call))
285 {
286 AEException bug(call->toString());
287 addBugToReporter(bug, call);
288 }
289 }
290 else
291 {
292 // Handle other cases
293 }
294}
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:55
Map< std::string, std::vector< std::pair< u32_t, u32_t > > > extAPIBufOverflowCheckRules
Rules for checking buffer overflows in external APIs.
Definition AEDetector.h:326
bool canSafelyAccessMemory(const ValVar *value, const IntervalValue &len, const ICFGNode *node)
Checks if memory can be safely accessed.
bool detectStrcpy(const CallICFGNode *call)
Detects buffer overflow in 'strcpy' function calls.
bool detectStrcat(const CallICFGNode *call)
Detects buffer overflow in 'strcat' 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
virtual const std::string & getName() const
Definition SVFValue.h:184
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64

◆ detectStrcat()

bool BufOverflowDetector::detectStrcat ( const CallICFGNode *  call)
private

Detects buffer overflow in 'strcat' function calls.

Parameters
callPointer to the call ICFG node.
Returns
True if a buffer overflow is detected, false otherwise.

Definition at line 421 of file AEDetector.cpp.

422{
424 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
425 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
426
427 if (std::find(strcatGroup.begin(), strcatGroup.end(), call->getCalledFunction()->getName()) != strcatGroup.end())
428 {
429 const ValVar* arg0Val = call->getArgument(0);
430 const ValVar* arg1Val = call->getArgument(1);
431 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
432 IntervalValue strLen1 = ae.getUtils()->getStrlen(arg1Val, call);
435 }
436 else if (std::find(strncatGroup.begin(), strncatGroup.end(), call->getCalledFunction()->getName()) != strncatGroup.end())
437 {
438 const ValVar* arg0Val = call->getArgument(0);
439 const ValVar* arg2Val = call->getArgument(2);
440 IntervalValue arg2Num = ae.getAbsValue(arg2Val, call).getInterval();
441 IntervalValue strLen0 = ae.getUtils()->getStrlen(arg0Val, call);
444 }
445 else
446 {
447 assert(false && "Unknown strcat function, please add it to strcatGroup or strncatGroup");
448 abort();
449 }
450}

◆ detectStrcpy()

bool BufOverflowDetector::detectStrcpy ( const CallICFGNode *  call)
private

Detects buffer overflow in 'strcpy' function calls.

Parameters
callPointer to the call ICFG node.
Returns
True if a buffer overflow is detected, false otherwise.

This function checks if the destination buffer can safely accommodate the source string being copied, accounting for the null terminator.

Parameters
asReference to the abstract state.
callPointer to the call ICFG node.
Returns
True if the memory access is safe, false otherwise.

Definition at line 412 of file AEDetector.cpp.

413{
414 const ValVar* arg0Val = call->getArgument(0);
415 const ValVar* arg1Val = call->getArgument(1);
417 IntervalValue strLen = ae.getUtils()->getStrlen(arg1Val, call);
418 return canSafelyAccessMemory(arg0Val, strLen, call);
419}

◆ getAccessOffset()

IntervalValue BufOverflowDetector::getAccessOffset ( SVF::NodeID  objId,
const GepStmt *  gep 
)

Retrieves the access offset for a given object and GEP statement.

Parameters
asReference to the abstract state.
objIdThe ID of the object.
gepPointer to the GEP statement.
Returns
The interval value of the access offset.

This function calculates the access offset for a base object or a sub-object of an aggregate object (using GEP). If the object is a dummy object, it returns a top interval value.

Parameters
objIdThe ID of the object.
gepPointer to the GEP statement.
Returns
The interval value of the access offset.

Definition at line 306 of file AEDetector.cpp.

307{
308 SVFIR* svfir = PAG::getPAG();
310 auto obj = svfir->getSVFVar(objId);
311
312 if (SVFUtil::isa<BaseObjVar>(obj))
313 {
314 return ae.getGepByteOffset(gep);
315 }
316 else if (SVFUtil::isa<GepObjVar>(obj))
317 {
318 return getGepObjOffsetFromBase(SVFUtil::cast<GepObjVar>(obj)) + ae.getGepByteOffset(gep);
319 }
320 else
321 {
322 assert(SVFUtil::isa<DummyObjVar>(obj) && "Unknown object type");
323 return IntervalValue::top();
324 }
325}
static IntervalValue top()
Create the IntervalValue [-inf, +inf].

◆ getGepObjOffsetFromBase()

IntervalValue SVF::BufOverflowDetector::getGepObjOffsetFromBase ( const GepObjVar *  obj) const
inline

Retrieves the offset of a GEP object from its base.

Parameters
objPointer to the GEP object.
Returns
The interval value of the offset.

Definition at line 217 of file AEDetector.h.

218 {
220 return gepObjOffsetFromBase.at(obj);
221 else
222 {
223 assert(false && "GepObjVar not found in gepObjOffsetFromBase");
224 abort();
225 }
226 }
bool hasGepObjOffsetFromBase(const GepObjVar *obj) const
Checks if a GEP object has an associated offset.
Definition AEDetector.h:207

◆ handleStubFunctions()

void BufOverflowDetector::handleStubFunctions ( const CallICFGNode *  callNode)
overridevirtual

Handles external API calls related to buffer overflow detection.

Handles stub functions within the ICFG node.

Parameters
callPointer to the call ICFG node.

This function is a placeholder for handling stub functions within the ICFG node.

Parameters
nodePointer to the ICFG node.

Implements SVF::AEDetector.

Definition at line 117 of file AEDetector.cpp.

118{
119 // get function name
120 std::string funcName = callNode->getCalledFunction()->getName();
122 if (funcName == "SAFE_BUFACCESS")
123 {
124 ae.getUtils()->checkpoints.erase(callNode);
125 if (callNode->arg_size() < 2)
126 return;
127 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
128 if (val.isBottom())
129 {
130 val = IntervalValue(0);
131 assert(false && "SAFE_BUFACCESS size is bottom");
132 }
133 const ValVar* arg0Val = callNode->getArgument(0);
135 if (isSafe)
136 {
137 SVFUtil::outs() << SVFUtil::sucMsg("success: expected safe buffer access at SAFE_BUFACCESS")
138 << " — " << callNode->toString() << "\n";
139 return;
140 }
141 else
142 {
143 SVFUtil::outs() << SVFUtil::errMsg("failure: unexpected buffer overflow at SAFE_BUFACCESS")
144 << " — Position: " << callNode->getSourceLoc() << "\n";
145 assert(false);
146 }
147 }
148 else if (funcName == "UNSAFE_BUFACCESS")
149 {
150 ae.getUtils()->checkpoints.erase(callNode);
151 if (callNode->arg_size() < 2) return;
152 IntervalValue val = ae.getAbsValue(callNode->getArgument(1), callNode).getInterval();
153 if (val.isBottom())
154 {
155 assert(false && "UNSAFE_BUFACCESS size is bottom");
156 }
157 const ValVar* arg0Val = callNode->getArgument(0);
159 if (!isSafe)
160 {
161 SVFUtil::outs() << SVFUtil::sucMsg("success: expected buffer overflow at UNSAFE_BUFACCESS")
162 << " — " << callNode->toString() << "\n";
163 return;
164 }
165 else
166 {
167 SVFUtil::outs() << SVFUtil::errMsg("failure: buffer overflow expected at UNSAFE_BUFACCESS, but none detected")
168 << " — Position: " << callNode->getSourceLoc() << "\n";
169 assert(false);
170 }
171 }
172}
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 & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:58

◆ hasGepObjOffsetFromBase()

bool SVF::BufOverflowDetector::hasGepObjOffsetFromBase ( const GepObjVar *  obj) const
inline

Checks if a GEP object has an associated offset.

Parameters
objPointer to the GEP object.
Returns
True if the GEP object has an offset, false otherwise.

Definition at line 207 of file AEDetector.h.

208 {
209 return gepObjOffsetFromBase.find(obj) != gepObjOffsetFromBase.end();
210 }

◆ initExtAPIBufOverflowCheckRules()

void BufOverflowDetector::initExtAPIBufOverflowCheckRules ( )

Initializes external API buffer overflow check rules.

This function sets up rules for various memory-related functions like memcpy, memset, etc., defining which arguments should be checked for buffer overflows.

Definition at line 180 of file AEDetector.cpp.

181{
182 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
183 extAPIBufOverflowCheckRules["llvm_memcpy_p0_p0_i64"] = {{0, 2}, {1, 2}};
184 extAPIBufOverflowCheckRules["llvm_memcpy_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
185 extAPIBufOverflowCheckRules["llvm_memcpy"] = {{0, 2}, {1, 2}};
186 extAPIBufOverflowCheckRules["llvm_memmove"] = {{0, 2}, {1, 2}};
187 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i64"] = {{0, 2}, {1, 2}};
188 extAPIBufOverflowCheckRules["llvm_memmove_p0_p0_i64"] = {{0, 2}, {1, 2}};
189 extAPIBufOverflowCheckRules["llvm_memmove_p0i8_p0i8_i32"] = {{0, 2}, {1, 2}};
190 extAPIBufOverflowCheckRules["__memcpy_chk"] = {{0, 2}, {1, 2}};
191 extAPIBufOverflowCheckRules["memmove"] = {{0, 2}, {1, 2}};
192 extAPIBufOverflowCheckRules["bcopy"] = {{0, 2}, {1, 2}};
193 extAPIBufOverflowCheckRules["memccpy"] = {{0, 3}, {1, 3}};
194 extAPIBufOverflowCheckRules["__memmove_chk"] = {{0, 2}, {1, 2}};
195 extAPIBufOverflowCheckRules["llvm_memset"] = {{0, 2}};
196 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i32"] = {{0, 2}};
197 extAPIBufOverflowCheckRules["llvm_memset_p0i8_i64"] = {{0, 2}};
198 extAPIBufOverflowCheckRules["llvm_memset_p0_i64"] = {{0, 2}};
199 extAPIBufOverflowCheckRules["__memset_chk"] = {{0, 2}};
200 extAPIBufOverflowCheckRules["wmemset"] = {{0, 2}};
201 extAPIBufOverflowCheckRules["strncpy"] = {{0, 2}, {1, 2}};
202 extAPIBufOverflowCheckRules["iconv"] = {{1, 2}, {3, 4}};
203}

◆ reportBug()

void SVF::BufOverflowDetector::reportBug ( )
inlineoverridevirtual

Reports all detected buffer overflow bugs.

Implements SVF::AEDetector.

Definition at line 274 of file AEDetector.h.

275 {
276 if (!nodeToBugInfo.empty())
277 {
278 std::cerr << "######################Buffer Overflow (" + std::to_string(nodeToBugInfo.size())
279 + " found)######################\n";
280 std::cerr << "---------------------------------------------\n";
281 for (const auto& it : nodeToBugInfo)
282 {
283 std::cerr << it.second << "\n---------------------------------------------\n";
284 }
285 }
286 }

◆ updateGepObjOffsetFromBase()

void BufOverflowDetector::updateGepObjOffsetFromBase ( const ICFGNode *  node,
SVF::AddressValue  gepAddrs,
SVF::AddressValue  objAddrs,
SVF::IntervalValue  offset 
)

Updates the offset of a GEP object from its base.

Parameters
asReference to the abstract state.
gepAddrsAddress value for GEP.
objAddrsAddress value for the object.
offsetThe interval value of the offset.

This function calculates and stores the offset of a GEP object from its base object using the addresses and offsets provided.

Parameters
gepAddrsThe addresses of the GEP objects.
objAddrsThe addresses of the base objects.
offsetThe interval value of the offset.

Definition at line 337 of file AEDetector.cpp.

338{
339 SVFIR* svfir = PAG::getPAG();
341 const AbstractState& as = ae.getAbsState(node);
342
343 for (const auto& objAddr : objAddrs)
344 {
346 auto obj = svfir->getSVFVar(objId);
347
348 if (SVFUtil::isa<BaseObjVar>(obj))
349 {
350 // if the object is a BaseObjVar, add the offset directly
351 // like llvm bc `arr = alloc i8 12; p = gep arr, 4`
352 // we write key value pair {gep, 4}
353 for (const auto& gepAddr : gepAddrs)
354 {
355 NodeID gepObj = as.getIDFromAddr(gepAddr);
356 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getSVFVar(gepObj)))
357 {
359 }
360 else
361 {
363 "GEP object is neither a GepObjVar nor an address without a backing object");
364 }
365 }
366 }
367 else if (SVFUtil::isa<GepObjVar>(obj))
368 {
369 // if the object is a GepObjVar, add the offset from the base object
370 // like llvm bc `arr = alloc i8 12; p = gep arr, 4; q = gep p, 6`
371 // we retreive {p, 4} and write {q, 4+6}
372 const GepObjVar* objVar = SVFUtil::cast<GepObjVar>(obj);
373 for (const auto& gepAddr : gepAddrs)
374 {
375 NodeID gepObj = as.getIDFromAddr(gepAddr);
376 if (const GepObjVar* gepObjVar = SVFUtil::dyn_cast<GepObjVar>(svfir->getSVFVar(gepObj)))
377 {
379 {
385 }
386 else
387 {
388 assert(false &&
389 "GEP RHS object has no offset from base");
390 }
391 }
392 else
393 {
395 "GEP object is neither a GepObjVar nor an address without a backing object");
396 }
397 }
398 }
399 }
400}
u32_t getIDFromAddr(u32_t addr) const
Return the internal index if addr is an address otherwise return the value of idx.
void addToGepObjOffsetFromBase(const GepObjVar *obj, const IntervalValue &offset)
Adds an offset to a GEP object.
Definition AEDetector.h:197

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 140 of file AEDetector.h.

Member Data Documentation

◆ bugLoc

Set<std::string> SVF::BufOverflowDetector::bugLoc
private

Set of locations where bugs have been reported.

Definition at line 327 of file AEDetector.h.

◆ extAPIBufOverflowCheckRules

Map<std::string, std::vector<std::pair<u32_t, u32_t> > > SVF::BufOverflowDetector::extAPIBufOverflowCheckRules
private

Rules for checking buffer overflows in external APIs.

Definition at line 326 of file AEDetector.h.

◆ gepObjOffsetFromBase

Map<const GepObjVar*, IntervalValue> SVF::BufOverflowDetector::gepObjOffsetFromBase
private

Maps GEP objects to their offsets from the base.

Definition at line 325 of file AEDetector.h.

◆ nodeToBugInfo

Map<const ICFGNode*, std::string> SVF::BufOverflowDetector::nodeToBugInfo
private

Maps ICFG nodes to bug information.

Definition at line 329 of file AEDetector.h.

◆ recoder

SVFBugReport SVF::BufOverflowDetector::recoder
private

Recorder for abstract execution bugs.

Definition at line 328 of file AEDetector.h.


The documentation for this class was generated from the following files: