Skip to content

Commit

Permalink
final commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bjjwwang committed Sep 9, 2024
1 parent 202b4d9 commit e29e780
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 18 deletions.
13 changes: 13 additions & 0 deletions svf/include/AE/Svfexe/AEDetector.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ class AEDetector
*/
virtual void detect(AbstractState& as, const ICFGNode* node) = 0;

/**
* @brief Pure virtual function for handling stub external API calls. (e.g. UNSAFE_BUFACCESS)
* @param call Pointer to the ext call ICFG node.
*/
virtual void handleStubFunctions(const CallICFGNode* call) = 0;

/**
* @brief Pure virtual function to report detected bugs.
*/
Expand Down Expand Up @@ -169,6 +175,13 @@ class BufOverflowDetector : public AEDetector
*/
void detect(AbstractState& as, const ICFGNode*);


/**
* @brief Handles external API calls related to buffer overflow detection.
* @param call Pointer to the call ICFG node.
*/
void handleStubFunctions(const CallICFGNode*);

/**
* @brief Adds an offset to a GEP object.
* @param obj Pointer to the GEP object.
Expand Down
32 changes: 16 additions & 16 deletions svf/include/AE/Svfexe/AbstractInterpretation.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ class AbstractInterpretation
detectors.push_back(std::move(detector));
}

protected:
Set<const CallICFGNode*> checkpoints; // for CI check

private:
/// Global ICFGNode is handled at the entry of the program,
virtual void handleGlobalNode();

Expand Down Expand Up @@ -252,18 +254,6 @@ class AbstractInterpretation
Map<const SVFFunction*, ICFGWTO*> funcToWTO;
Set<const SVFFunction*> recursiveFuns;

private:
// helper functions in handleCallSite
virtual bool isExtCall(const CallICFGNode* callNode);
virtual void extCallPass(const CallICFGNode* callNode);
virtual bool isRecursiveCall(const CallICFGNode* callNode);
virtual void recursiveCallPass(const CallICFGNode* callNode);
virtual bool isDirectCall(const CallICFGNode* callNode);
virtual void directCallFunPass(const CallICFGNode* callNode);
virtual bool isIndirectCall(const CallICFGNode* callNode);
virtual void indirectCallFunPass(const CallICFGNode* callNode);

protected:

AbstractState& getAbsStateFromTrace(const ICFGNode* node)
{
Expand All @@ -289,16 +279,26 @@ class AbstractInterpretation
return utils;
}

protected:
// helper functions in handleCallSite
virtual bool isExtCall(const CallICFGNode* callNode);
virtual void extCallPass(const CallICFGNode* callNode);
virtual bool isRecursiveCall(const CallICFGNode* callNode);
virtual void recursiveCallPass(const CallICFGNode* callNode);
virtual bool isDirectCall(const CallICFGNode* callNode);
virtual void directCallFunPass(const CallICFGNode* callNode);
virtual bool isIndirectCall(const CallICFGNode* callNode);
virtual void indirectCallFunPass(const CallICFGNode* callNode);

// there data should be shared with subclasses
Map<std::string, std::function<void(const CallICFGNode*)>> func_map;
Set<const CallICFGNode*> checkpoints;
Set<std::string> checkpoint_names;

Map<const ICFGNode*, AbstractState> abstractTrace; // abstract states immediately after nodes
std::string moduleName;

std::vector<std::unique_ptr<AEDetector>> detectors;
AbsExtAPI* utils;



};
}
79 changes: 79 additions & 0 deletions svf/lib/AE/Svfexe/AEDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,85 @@ void BufOverflowDetector::detect(AbstractState& as, const ICFGNode* node)
}
}


/**
* @brief Handles stub functions within the ICFG node.
*
* This function is a placeholder for handling stub functions within the ICFG node.
*
* @param node Pointer to the ICFG node.
*/
void BufOverflowDetector::handleStubFunctions(const SVF::CallICFGNode* callNode)
{
// get function name
SVFIR* svfir = PAG::getPAG();
std::string funcName = callNode->getCalledFunction()->getName();
if (funcName == "SAFE_BUFACCESS")
{
// void SAFE_BUFACCESS(void* data, int size);
AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
if (callNode->arg_size() < 2)
return;
AbstractState& as =
AbstractInterpretation::getAEInstance().getAbsStateFromTrace(
callNode);
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
IntervalValue val = as[size_id].getInterval();
if (val.isBottom())
{
val = IntervalValue(0);
assert(false && "SAFE_BUFACCESS size is bottom");

Check warning on line 132 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L132

Added line #L132 was not covered by tests
}
const SVFVar* arg0Val =
AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(
callNode->getArgument(0));
bool isSafe = canSafelyAccessMemory(as, arg0Val, val);
if (isSafe)
{
std::cout << "safe buffer access success: " << callNode->toString()
<< std::endl;
return;
}
else
{
std::string err_msg = "this SAFE_BUFACCESS should be a safe access but detected buffer overflow. Pos: ";
err_msg += callNode->getSourceLoc();

Check warning on line 147 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L146-L147

Added lines #L146 - L147 were not covered by tests
std::cerr << err_msg << std::endl;
assert(false);

Check warning on line 149 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L149

Added line #L149 was not covered by tests
}
}
else if (funcName == "UNSAFE_BUFACCESS")
{
// handle other stub functions
//void UNSAFE_BUFACCESS(void* data, int size);
AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
if (callNode->arg_size() < 2) return;
AbstractState&as = AbstractInterpretation::getAEInstance().getAbsStateFromTrace(callNode);
u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
IntervalValue val = as[size_id].getInterval();
if (val.isBottom())
{
assert(false && "UNSAFE_BUFACCESS size is bottom");

Check warning on line 163 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L163

Added line #L163 was not covered by tests
}
const SVFVar* arg0Val =
AbstractInterpretation::getAEInstance().getUtils()->getSVFVar(
callNode->getArgument(0));
bool isSafe = canSafelyAccessMemory(as, arg0Val, val);
if (!isSafe)
{
std::cout << "detect buffer overflow success: " << callNode->toString() << std::endl;
return;
}
else
{
std::string err_msg = "this UNSAFE_BUFACCESS should be a buffer overflow but not detected. Pos: ";
err_msg += callNode->getSourceLoc();

Check warning on line 177 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L176-L177

Added lines #L176 - L177 were not covered by tests
std::cerr << err_msg << std::endl;
assert(false);

Check warning on line 179 in svf/lib/AE/Svfexe/AEDetector.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AEDetector.cpp#L179

Added line #L179 was not covered by tests
}
}
}

/**
* @brief Initializes external API buffer overflow check rules.
*
Expand Down
15 changes: 15 additions & 0 deletions svf/lib/AE/Svfexe/AbsExtAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
// Created by Jiawei Wang on 2024/9/9.
//
#include "AE/Svfexe/AbsExtAPI.h"
#include "AE/Svfexe/AbstractInterpretation.h"

using namespace SVF;
AbsExtAPI::AbsExtAPI(Map<const ICFGNode*, AbstractState>& traces): abstractTrace(traces)
Expand Down Expand Up @@ -71,6 +72,7 @@ void AbsExtAPI::initExtFunMap()

auto sse_svf_assert = [this](const CallICFGNode* callNode)
{
AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
u32_t arg0 = svfir->getValueNode(callNode->getArgument(0));
AbstractState&as = getAbsStateFromTrace(callNode);
if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
Expand Down Expand Up @@ -340,6 +342,19 @@ void AbsExtAPI::initExtFunMap()
func_map["__recv"] = sse_recv;
};

AbstractState& AbsExtAPI::getAbsStateFromTrace(const SVF::ICFGNode* node)
{
const ICFGNode* repNode = icfg->getRepNode(node);
if (abstractTrace.count(repNode) == 0)
{
assert(0 && "No preAbsTrace for this node");

Check warning on line 350 in svf/lib/AE/Svfexe/AbsExtAPI.cpp

View check run for this annotation

Codecov / codecov/patch

svf/lib/AE/Svfexe/AbsExtAPI.cpp#L350

Added line #L350 was not covered by tests
}
else
{
return abstractTrace[repNode];
}
}

std::string AbsExtAPI::strRead(AbstractState& as, const SVFVar* rhs)
{
// sse read string nodeID->string
Expand Down
17 changes: 15 additions & 2 deletions svf/lib/AE/Svfexe/AbstractInterpretation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,9 @@ void AbstractInterpretation::extCallPass(const SVF::CallICFGNode *callNode)
{
callSiteStack.push_back(callNode);
utils->handleExtAPI(callNode);
for (auto& detector : detectors) {
detector->handleStubFunctions(callNode);
}
callSiteStack.pop_back();
}

Expand Down Expand Up @@ -959,18 +962,28 @@ void AEStat::performStat()
void AbstractInterpretation::collectCheckPoint()
{
// traverse every ICFGNode
Set<std::string> ae_checkpoint_names = {"svf_assert"};
Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};

for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
{
const ICFGNode* node = it->second;
if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
{
if (const SVFFunction *fun = call->getCalledFunction())
{
if (checkpoint_names.find(fun->getName()) !=
checkpoint_names.end())
if (ae_checkpoint_names.find(fun->getName()) !=
ae_checkpoint_names.end())
{
checkpoints.insert(call);
}
if (Options::BufferOverflowCheck()) {
if (buf_checkpoint_names.find(fun->getName()) !=
buf_checkpoint_names.end())
{
checkpoints.insert(call);
}
}
}
}
}
Expand Down

0 comments on commit e29e780

Please sign in to comment.