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

#include <AEDetector.h>

Inheritance diagram for SVF::NullptrDerefDetector:
SVF::AEDetector

Public Member Functions

 NullptrDerefDetector ()
 
 ~NullptrDerefDetector ()=default
 
void detect (const ICFGNode *node) override
 Detects nullptr dereferences issues within a node.
 
void handleStubFunctions (const CallICFGNode *call) override
 Handles external API calls related to nullptr dereferences.
 
bool isUninit (AbstractValue v)
 Checks if an Abstract Value is uninitialized.
 
void addBugToReporter (const AEException &e, const ICFGNode *node)
 Adds a bug to the reporter based on an exception.
 
void reportBug () override
 Reports all detected nullptr dereference bugs.
 
void detectExtAPI (const CallICFGNode *call)
 Handle external API calls related to nullptr dereferences.
 
bool isNull (AbstractValue v)
 Check if an Abstract Value is NULL (or uninitialized).
 
bool canSafelyDerefPtr (const ValVar *ptr, const ICFGNode *node)
 
- 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)
 
- Static Public Member Functions inherited from SVF::AEDetector
static bool classof (const AEDetector *detector)
 Check if the detector is of the UNKNOWN kind.
 

Private Attributes

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

Definition at line 332 of file AEDetector.h.

Constructor & Destructor Documentation

◆ NullptrDerefDetector()

SVF::NullptrDerefDetector::NullptrDerefDetector ( )
inline

Definition at line 336 of file AEDetector.h.

337 {
339 }
@ NULL_DEREF
Detector for nullptr dereference issues.
Definition AEDetector.h:53
DetectorKind kind
The kind of the detector.
Definition AEDetector.h:105

◆ ~NullptrDerefDetector()

SVF::NullptrDerefDetector::~NullptrDerefDetector ( )
default

Member Function Documentation

◆ addBugToReporter()

void SVF::NullptrDerefDetector::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 378 of file AEDetector.h.

379 {
382 eventStack.push_back(sourceInstEvent); // Add the source instruction event to the event stack
383
384 if (eventStack.empty())
385 {
386 return; // If the event stack is empty, return early
387 }
388 std::string loc = eventStack.back().getEventLoc(); // Get the location of the last event in the stack
389
390 // Check if the bug at this location has already been reported
391 if (bugLoc.find(loc) != bugLoc.end())
392 {
393 return; // If the bug location is already reported, return early
394 }
395 else
396 {
397 bugLoc.insert(loc); // Otherwise, mark this location as reported
398 }
400 nodeToBugInfo[node] = e.what(); // Record the exception information for the node
401 }
std::vector< SVFBugEvent > EventStack
Set< std::string > bugLoc
Set of locations where bugs have been reported.
Definition AEDetector.h:441
SVFBugReport recoder
Recorder for abstract execution bugs.
Definition AEDetector.h:442
Map< const ICFGNode *, std::string > nodeToBugInfo
Maps ICFG nodes to bug information.
Definition AEDetector.h:443
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

◆ canSafelyDerefPtr()

bool NullptrDerefDetector::canSafelyDerefPtr ( const ValVar ptr,
const ICFGNode node 
)

Definition at line 666 of file AEDetector.cpp.

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}
static AbstractInterpretation & getAEInstance()
static bool isNullMem(u32_t addr)
static bool isBlackHoleObjAddr(u32_t addr)
bool isUninit(AbstractValue v)
Checks if an Abstract Value is uninitialized.
Definition AEDetector.h:366

◆ classof()

static bool SVF::NullptrDerefDetector::classof ( const AEDetector detector)
inlinestatic

Definition at line 343 of file AEDetector.h.

344 {
345 return detector->getKind() == AEDetector::NULL_DEREF;
346 }

◆ detect()

void NullptrDerefDetector::detect ( const ICFGNode node)
overridevirtual

Detects nullptr dereferences issues within a node.

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

Implements SVF::AEDetector.

Definition at line 514 of file AEDetector.cpp.

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}
Exception class for handling errors in Abstract Execution.
Definition AEDetector.h:113
bool canSafelyDerefPtr(const ValVar *ptr, const ICFGNode *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.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437

◆ detectExtAPI()

void NullptrDerefDetector::detectExtAPI ( const CallICFGNode call)

Handle external API calls related to nullptr dereferences.

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

Definition at line 607 of file AEDetector.cpp.

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}
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

◆ handleStubFunctions()

void NullptrDerefDetector::handleStubFunctions ( const CallICFGNode call)
overridevirtual

Handles external API calls related to nullptr dereferences.

Parameters
callPointer to the call ICFG node.

Implements SVF::AEDetector.

Definition at line 557 of file AEDetector.cpp.

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}
NodeID getId() const
Get ID.
Definition SVFValue.h:163
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

◆ isNull()

bool SVF::NullptrDerefDetector::isNull ( AbstractValue  v)
inline

Check if an Abstract Value is NULL (or uninitialized).

Parameters
vAn Abstract Value of loaded from an address in an Abstract State.

Definition at line 433 of file AEDetector.h.

434 {
435 return !v.isAddr() && !v.isInterval();
436 }

◆ isUninit()

bool SVF::NullptrDerefDetector::isUninit ( AbstractValue  v)
inline

Checks if an Abstract Value is uninitialized.

Parameters
vThe Abstract Value to check.
Returns
True if the value is uninitialized, false otherwise.

Definition at line 366 of file AEDetector.h.

367 {
368 // uninitialized value has neither interval value nor address value
369 bool is = v.getAddrs().isBottom() && v.getInterval().isBottom();
370 return is;
371 }

◆ reportBug()

void SVF::NullptrDerefDetector::reportBug ( )
inlineoverridevirtual

Reports all detected nullptr dereference bugs.

Implements SVF::AEDetector.

Definition at line 406 of file AEDetector.h.

407 {
408 if (!nodeToBugInfo.empty())
409 {
410 std::cerr << "###################### Nullptr Dereference (" + std::to_string(nodeToBugInfo.size())
411 + " found)######################\n";
412 std::cerr << "---------------------------------------------\n";
413 for (const auto& it : nodeToBugInfo)
414 {
415 std::cerr << it.second << "\n---------------------------------------------\n";
416 }
417 }
418 }

Friends And Related Symbol Documentation

◆ AbstractInterpretation

Definition at line 334 of file AEDetector.h.

Member Data Documentation

◆ bugLoc

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

Set of locations where bugs have been reported.

Definition at line 441 of file AEDetector.h.

◆ nodeToBugInfo

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

Maps ICFG nodes to bug information.

Definition at line 443 of file AEDetector.h.

◆ recoder

SVFBugReport SVF::NullptrDerefDetector::recoder
private

Recorder for abstract execution bugs.

Definition at line 442 of file AEDetector.h.


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