40 #define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
41 auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
43 AbstractState& as = getAbsStateFromTrace(callNode); \
44 u32_t rhs_id = callNode->getArgument(0)->getId(); \
45 if (!as.inVarToValTable(rhs_id)) return; \
46 u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
47 s32_t res = FUNC_NAME(rhs); \
48 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId(); \
49 as[lhsId] = IntervalValue(res); \
52 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
73 auto sse_svf_assert = [
this](
const CallICFGNode* callNode)
76 u32_t arg0 = callNode->getArgument(0)->getId();
84 SVFUtil::errs() <<
"svf_assert Fail. " << callNode->toString() <<
"\n";
89 func_map[
"svf_assert"] = sse_svf_assert;
91 auto svf_assert_eq = [
this](
const CallICFGNode* callNode)
93 u32_t arg0 = callNode->getArgument(0)->getId();
94 u32_t arg1 = callNode->getArgument(1)->getId();
96 if (as[arg0].getInterval().equals(as[arg1].getInterval()))
102 SVFUtil::errs() <<
"svf_assert_eq Fail. " << callNode->toString() <<
"\n";
107 func_map[
"svf_assert_eq"] = svf_assert_eq;
111 if (callNode->arg_size() < 2)
return;
113 u32_t num_id = callNode->getArgument(0)->getId();
117 std::cout <<
"Text: " << text <<
", Value: " << callNode->getArgument(0)->
toString()
118 <<
", PrintVal: " << itv.
toString() <<
", Loc:" << callNode->getSourceLoc() << std::endl;
125 if (callNode->arg_size() < 2)
return;
133 const ICFGNode* node = SVFUtil::cast<ICFGNode>(
134 SVFUtil::cast<ValVar>(callNode->getArgument(0))->getGNode());
137 if (SVFUtil::isa<LoadStmt>(stmt))
139 const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
146 func_map[
"set_value"] = svf_set_value;
152 if (callNode->arg_size() < 2)
return;
154 u32_t dst_id = callNode->getArgument(1)->getId();
166 as.
store(vaddr, range);
173 if (callNode->arg_size() < 3)
return;
175 u32_t dst_id = callNode->getArgument(2)->getId();
186 as.
store(vaddr, range);
191 func_map[
"__isoc99_fscanf"] = sse_fscanf;
192 func_map[
"__isoc99_scanf"] = sse_scanf;
193 func_map[
"__isoc99_vscanf"] = sse_scanf;
197 func_map[
"__isoc99_sscanf"] = sse_scanf;
202 if (callNode->arg_size() < 3)
return;
204 u32_t block_count_id = callNode->getArgument(2)->getId();
205 u32_t block_size_id = callNode->getArgument(1)->getId();
206 IntervalValue block_count = as[block_count_id].getInterval();
219 if (callNode->arg_size() < 2)
return;
221 u32_t size_id = callNode->getArgument(1)->getId();
222 u32_t dst_id = callNode->getArgument(0)->getId();
225 if (callNode->getArgument(2)->getType()->isArrayTy())
227 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
228 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
230 else if (callNode->getArgument(2)->getType()->isPointerTy())
244 func_map[
"__snprintf_chk"] = sse_snprintf;
245 func_map[
"__vsprintf_chk"] = sse_sprintf;
246 func_map[
"__sprintf_chk"] = sse_sprintf;
247 func_map[
"snprintf"] = sse_snprintf;
250 func_map[
"vsnprintf"] = sse_snprintf;
251 func_map[
"__vsnprintf_chk"] = sse_snprintf;
252 func_map[
"swprintf"] = sse_snprintf;
253 func_map[
"_snwprintf"] = sse_snprintf;
260 if (callNode->arg_size() < 3)
return;
262 u32_t num_id = callNode->getArgument(0)->getId();
264 u32_t num = (
u32_t) as[num_id].getInterval().getNumeral();
273 if (callNode->arg_size() < 1)
return;
274 const SVFVar* strValue = callNode->getArgument(0);
277 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
279 for (
const auto& addr : as[value_id].getAddrs())
291 if (
const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
307 for (
const auto &addr: expr0.
getAddrs())
333 if (callNode->arg_size() < 4)
return;
335 u32_t len_id = callNode->getArgument(2)->getId();
337 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
349 assert(0 &&
"No preAbsTrace for this node");
370 for (
const auto &addr: expr0.
getAddrs())
391 assert(fun &&
"SVFFunction* is nullptr");
396 if (annotation.find(
"MEMCPY") != std::string::npos)
398 if (annotation.find(
"MEMSET") != std::string::npos)
400 if (annotation.find(
"STRCPY") != std::string::npos)
402 if (annotation.find(
"STRCAT") != std::string::npos)
415 u32_t lhsId = ret->getId();
429 else if (extType ==
MEMCPY)
435 else if (extType ==
MEMSET)
442 else if (extType ==
STRCPY)
446 else if (extType ==
STRCAT)
473 for (
const auto& addr : as[value_id].getAddrs())
485 if (
const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
501 for (
const auto &addr: expr0.
getAddrs())
513 elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->
getType())->getTypeOfElement()->getByteSize();
519 if (elemType->isArrayTy())
520 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
522 elemSize = elemType->getByteSize();
531 assert(
false &&
"we cannot support this type");
551 const std::vector<std::string> strcatGroup = {
"__strcat_chk",
"strcat",
"__wcscat_chk",
"wcscat"};
552 const std::vector<std::string> strncatGroup = {
"__strncat_chk",
"strncat",
"__wcsncat_chk",
"wcsncat"};
553 if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->
getName()) != strcatGroup.end())
563 else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->
getName()) != strncatGroup.end())
576 assert(
false &&
"unknown strcat function, please add it to strcatGroup or strncatGroup");
587 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->
getType())->getTypeOfElement()->getByteSize();
594 if (elemType->isArrayTy())
595 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
597 elemSize = elemType->getByteSize();
606 assert(
false &&
"we cannot support this type");
609 u32_t range_val = size / elemSize;
619 for (
const auto &dst: expr_dst.
getAddrs())
621 for (
const auto &src: expr_src.
getAddrs())
645 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->
getType())->getTypeOfElement()->getByteSize();
651 elemSize = elemType->getByteSize();
660 assert(
false &&
"we cannot support this type");
663 u32_t range_val = size / elemSize;
670 for (
const auto &addr: lhs_gep.
getAddrs())
681 as.
store(addr, elem);
710 if (intType->isSigned())
712 ub =
static_cast<s64_t>(std::numeric_limits<s32_t>::max());
713 lb =
static_cast<s64_t>(std::numeric_limits<s32_t>::min());
717 ub =
static_cast<s64_t>(std::numeric_limits<u32_t>::max());
718 lb =
static_cast<s64_t>(std::numeric_limits<u32_t>::min());
723 if (intType->isSigned())
725 ub =
static_cast<s64_t>(std::numeric_limits<s16_t>::max());
726 lb =
static_cast<s64_t>(std::numeric_limits<s16_t>::min());
730 ub =
static_cast<s64_t>(std::numeric_limits<u16_t>::max());
731 lb =
static_cast<s64_t>(std::numeric_limits<u16_t>::min());
736 if (intType->isSigned())
738 ub =
static_cast<s64_t>(std::numeric_limits<int8_t>::max());
739 lb =
static_cast<s64_t>(std::numeric_limits<int8_t>::min());
743 ub =
static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
744 lb =
static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
749 else if (SVFUtil::isa<SVFOtherType>(
type))
752 s64_t ub =
static_cast<s64_t>(std::numeric_limits<s32_t>::max());
753 s64_t lb =
static_cast<s64_t>(std::numeric_limits<s32_t>::min());
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
std::string strRead(AbstractState &as, const SVFVar *rhs)
Reads a string from the abstract state.
void handleMemset(AbstractState &as, const SVFVar *dst, IntervalValue elem, IntervalValue len)
Handles the memset API call.
void initExtFunMap()
Initializes the external function map.
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculates the length of a string.
Map< const ICFGNode *, AbstractState > & abstractTrace
Map of ICFG nodes to abstract states.
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
AbsExtAPI(Map< const ICFGNode *, AbstractState > &traces)
Constructor for AbsExtAPI.
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
const SVFVar * getSVFVar(const SVFValue *val)
Retrieves the SVF variable from a given SVF value.
void handleMemcpy(AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
Handles the memcpy API call.
SVFIR * svfir
Pointer to the SVF intermediate representation.
void handleStrcat(const SVF::CallICFGNode *call)
Handles the strcat API call.
ExtAPIType
Enumeration of external API types.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
ICFG * icfg
Pointer to the interprocedural control flow graph.
void handleStrcpy(const CallICFGNode *call)
Handles the strcpy API call.
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
Set< const CallICFGNode * > checkpoints
static AbstractInterpretation & getAEInstance()
u32_t getAllocaInstByteSize(const AddrStmt *addr)
void store(u32_t addr, const AbstractValue &val)
virtual bool inAddrToValTable(u32_t id) const
whether the memory address stores abstract value
bool inAddrToAddrsTable(u32_t id) const
whether the memory address stores memory addresses
std::string toString() const
const SVFType * getPointeeElement(NodeID id)
virtual AbstractValue & load(u32_t addr)
bool inVarToAddrsTable(u32_t id) const
whether the variable is in varToAddrs table
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
virtual bool inVarToValTable(u32_t id) const
whether the variable is in varToVal table
void storeValue(NodeID varId, AbstractValue val)
AddressValue getGepObjAddrs(u32_t pointer, IntervalValue offset)
void join_with(const AbstractValue &other)
AddressValue & getAddrs()
IntervalValue & getInterval()
NodeID getRHSVarID() const
s64_t getIntNumeral() const
const SVFFunction * getCalledFunction() const
const RetICFGNode * getRetICFGNode() const
Return callsite.
const SVFVar * getArgument(u32_t ArgNo) const
Parameter operations.
static ExtAPI * getExtAPI()
NodeType * getGNode(NodeID id) const
Get a node.
bool hasGNode(NodeID id) const
Has a node.
const SVFStmtList & getSVFStmts() const
const ICFGNode * getRepNode(const ICFGNode *node) const
NodeID getValueNode(const SVFValue *V)
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
s64_t getIntNumeral() const
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
const BoundedInt & lb() const
Return the lower bound.
const std::string toString() const
const BoundedInt & ub() const
Return the upper bound.
void set_to_top()
Set current IntervalValue as top.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const SVFBaseNode * getGNode() const
Get the reference value to this object.
u32_t getByteSizeOfObj() const
Get the byte size of this object.
bool isConstantByteSize() const
Check if byte size is a const value.
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
const SVFVar * getActualRet() const
Return actual return parameter.
NodeID getId() const
Get ID.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
const MemObj * getBaseObj(NodeID id) const
u32_t getByteSize() const
const std::string & getName() const
virtual const SVFType * getType() const
Return type of the value.
int ispunct(int argument)
int isblank(int character)
int isalnum(int character)
int isalpha(int character)
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
std::ostream & errs()
Overwrite llvm::errs()
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map