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 (AbstractState &as, AddressValue gepAddrs, AddressValue objAddrs, IntervalValue offset)
 Updates the offset of a GEP object from its base.
 
void detect (AbstractState &as, const ICFGNode *)
 Detect buffer overflow issues within a node.
 
void handleStubFunctions (const CallICFGNode *)
 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 (AbstractState &as, 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 ()
 Reports all detected buffer overflow bugs.
 
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.
 
bool canSafelyAccessMemory (AbstractState &as, const SVFVar *value, const IntervalValue &len)
 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 (AbstractState &as, const CallICFGNode *call)
 Detects buffer overflow in 'strcat' function calls.
 
bool detectStrcpy (AbstractState &as, const CallICFGNode *call)
 Detects buffer overflow in 'strcpy' function calls.
 

Private Attributes

Map< const GepObjVar *, IntervalValuegepObjOffsetFromBase
 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 134 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 141 of file AEDetector.h.

142 {
145 }
@ BUF_OVERFLOW
Detector for buffer overflow issues.
Definition AEDetector.h:47
DetectorKind kind
The kind of the detector.
Definition AEDetector.h:100
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 235 of file AEDetector.h.

236 {
237
240 eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
241
242 if (eventStack.empty())
243 {
244 return; // If the event stack is empty, return early
245 }
246
247 std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
248
249 // Check if the bug at this location has already been reported
250 if (bugLoc.find(loc) != bugLoc.end())
251 {
252 return; // If the bug location is already reported, return early
253 }
254 else
255 {
256 bugLoc.insert(loc); // Otherwise, mark this location as reported
257 }
258
259 // Add the bug to the recorder with details from the event stack
261 nodeToBugInfo[node] = e.what(); // Record the exception information for the node
262 }
SVFBugReport recoder
Recorder for abstract execution bugs.
Definition AEDetector.h:323
Set< std::string > bugLoc
Set of locations where bugs have been reported.
Definition AEDetector.h:322
Map< const ICFGNode *, std::string > nodeToBugInfo
Maps ICFG nodes to bug information.
Definition AEDetector.h:324
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:74

◆ 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 193 of file AEDetector.h.

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

◆ canSafelyAccessMemory()

bool BufOverflowDetector::canSafelyAccessMemory ( AbstractState as,
const SVFVar value,
const IntervalValue len 
)

Checks if memory can be safely accessed.

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

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.

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 476 of file AEDetector.cpp.

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}
unsigned u32_t
Definition CommandLine.h:18
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:213
NodeType * getGNode(NodeID id) const
Get a node.
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
u32_t NodeID
Definition GeneralType.h:56

◆ 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 157 of file AEDetector.h.

158 {
159 return detector->getKind() == AEDetector::BUF_OVERFLOW;
160 }

◆ detect()

void BufOverflowDetector::detect ( AbstractState as,
const ICFGNode node 
)
virtual

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 44 of file AEDetector.cpp.

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}
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:108
IntervalValue getAccessOffset(AbstractState &as, NodeID objId, const GepStmt *gep)
Retrieves the access offset for a given object and GEP statement.
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
static IntervalValue bottom()
Create the bottom IntervalValue [+inf, -inf].
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437

◆ detectExtAPI()

void BufOverflowDetector::detectExtAPI ( AbstractState as,
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
asReference to the abstract state.
callPointer to the call ICFG node.

Definition at line 218 of file AEDetector.cpp.

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}
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
Map< std::string, std::vector< std::pair< u32_t, u32_t > > > extAPIBufOverflowCheckRules
Rules for checking buffer overflows in external APIs.
Definition AEDetector.h:321
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.
bool canSafelyAccessMemory(AbstractState &as, const SVFVar *value, const IntervalValue &len)
Checks if memory can be safely accessed.
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
virtual const std::string & getName() const
Definition SVFValue.h:184
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58

◆ detectStrcat()

bool BufOverflowDetector::detectStrcat ( AbstractState as,
const CallICFGNode call 
)
private

Detects buffer overflow in 'strcat' function calls.

Parameters
asReference to the abstract state.
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 both the existing string and the concatenated string from the source.

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 435 of file AEDetector.cpp.

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}
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.
static AbstractInterpretation & getAEInstance()

◆ detectStrcpy()

bool BufOverflowDetector::detectStrcpy ( AbstractState as,
const CallICFGNode call 
)
private

Detects buffer overflow in 'strcpy' function calls.

Parameters
asReference to the abstract state.
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 417 of file AEDetector.cpp.

◆ getAccessOffset()

IntervalValue BufOverflowDetector::getAccessOffset ( SVF::AbstractState as,
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
asReference to the abstract state.
objIdThe ID of the object.
gepPointer to the GEP statement.
Returns
The interval value of the access offset.

Definition at line 312 of file AEDetector.cpp.

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}
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 213 of file AEDetector.h.

214 {
216 return gepObjOffsetFromBase.at(obj);
217 else
218 assert(false && "GepObjVar not found in gepObjOffsetFromBase");
219 }
bool hasGepObjOffsetFromBase(const GepObjVar *obj) const
Checks if a GEP object has an associated offset.
Definition AEDetector.h:203

◆ handleStubFunctions()

void BufOverflowDetector::handleStubFunctions ( const CallICFGNode callNode)
virtual

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 114 of file AEDetector.cpp.

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}
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
Set< const CallICFGNode * > checkpoints
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 & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52

◆ 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 203 of file AEDetector.h.

204 {
205 return gepObjOffsetFromBase.find(obj) != gepObjOffsetFromBase.end();
206 }

◆ 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 184 of file AEDetector.cpp.

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}

◆ reportBug()

void SVF::BufOverflowDetector::reportBug ( )
inlinevirtual

Reports all detected buffer overflow bugs.

Implements SVF::AEDetector.

Definition at line 267 of file AEDetector.h.

268 {
269 if (!nodeToBugInfo.empty())
270 {
271 std::cerr << "######################Buffer Overflow (" + std::to_string(nodeToBugInfo.size())
272 + " found)######################\n";
273 std::cerr << "---------------------------------------------\n";
274 for (const auto& it : nodeToBugInfo)
275 {
276 std::cerr << it.second << "\n---------------------------------------------\n";
277 }
278 }
279 }

◆ updateGepObjOffsetFromBase()

void BufOverflowDetector::updateGepObjOffsetFromBase ( AbstractState as,
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 346 of file AEDetector.cpp.

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}
static bool isInvalidMem(u32_t addr)
void addToGepObjOffsetFromBase(const GepObjVar *obj, const IntervalValue &offset)
Adds an offset to a GEP object.
Definition AEDetector.h:193

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 136 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 322 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 321 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 320 of file AEDetector.h.

◆ nodeToBugInfo

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

Maps ICFG nodes to bug information.

Definition at line 324 of file AEDetector.h.

◆ recoder

SVFBugReport SVF::BufOverflowDetector::recoder
private

Recorder for abstract execution bugs.

Definition at line 323 of file AEDetector.h.


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