44#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
45 auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
47 assert(callNode->arg_size() >= 1 && "external function expects one argument"); \
48 const SVFVar* argVar = callNode->getArgument(0); \
49 const AbstractValue& argVal = ae->getAbsValue(argVar, callNode); \
50 IntervalValue result = IntervalValue::top(); \
51 if (argVal.isInterval() && argVal.getInterval().is_numeral()) { \
52 u32_t rhs = argVal.getInterval().lb().getIntNumeral(); \
53 result = IntervalValue(FUNC_NAME(rhs)); \
55 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet(); \
56 ae->updateAbsValue(retVar, result, callNode); \
58 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
79 auto sse_svf_assert = [
this](
const CallICFGNode* callNode)
82 const AbstractValue& arg0Val =
ae->getAbsValue(callNode->getArgument(0), callNode);
94 func_map[
"svf_assert"] = sse_svf_assert;
96 auto svf_assert_eq = [
this](
const CallICFGNode* callNode)
98 const AbstractValue& arg0Val =
ae->getAbsValue(callNode->getArgument(0), callNode);
99 const AbstractValue& arg1Val =
ae->getAbsValue(callNode->getArgument(1), callNode);
106 SVFUtil::errs() <<
"svf_assert_eq Fail. " << callNode->toString() <<
"\n";
111 func_map[
"svf_assert_eq"] = svf_assert_eq;
115 assert(callNode->arg_size() >= 2 &&
"svf_print expects two arguments");
116 std::string text =
strRead(callNode->getArgument(1), callNode);
117 IntervalValue itv =
ae->getAbsValue(callNode->getArgument(0), callNode).getInterval();
118 std::cout <<
"Text: " << text <<
", Value: " << callNode->getArgument(0)->toString()
119 <<
", PrintVal: " << itv.
toString() <<
", Loc:" << callNode->getSourceLoc() << std::endl;
126 assert(callNode->arg_size() >= 3 &&
"set_value expects three arguments");
128 const AbstractValue& lbVal =
ae->getAbsValue(callNode->getArgument(1), callNode);
129 const AbstractValue& ubVal =
ae->getAbsValue(callNode->getArgument(2), callNode);
134 ae->updateAbsValue(callNode->getArgument(0), num, callNode);
148 func_map[
"set_value"] = svf_set_value;
152 assert(callNode->arg_size() >= 3 &&
"fread expects at least three arguments");
153 IntervalValue block_count =
ae->getAbsValue(callNode->getArgument(2), callNode).getInterval();
154 IntervalValue block_size =
ae->getAbsValue(callNode->getArgument(1), callNode).getInterval();
167 assert(callNode->arg_size() >= 2 &&
168 "formatted-output function expects at least two arguments");
170 if (callNode->arg_size() > 2 &&
171 callNode->getArgument(2)->getType()->isArrayTy())
174 callNode->getArgument(2)->getType())
175 ->getTypeOfElement()->getByteSize();
177 IntervalValue size =
ae->getAbsValue(callNode->getArgument(1), callNode).getInterval()
181 func_map[
"__snprintf_chk"] = sse_snprintf;
182 func_map[
"__vsprintf_chk"] = sse_sprintf;
183 func_map[
"__sprintf_chk"] = sse_sprintf;
184 func_map[
"snprintf"] = sse_snprintf;
187 func_map[
"vsnprintf"] = sse_snprintf;
188 func_map[
"__vsnprintf_chk"] = sse_snprintf;
189 func_map[
"swprintf"] = sse_snprintf;
190 func_map[
"_snwprintf"] = sse_snprintf;
195 assert(callNode->arg_size() >= 3 &&
"itoa expects three arguments");
196 u32_t num = (
u32_t)
ae->getAbsValue(callNode->getArgument(0), callNode).getInterval().getNumeral();
197 std::string snum = std::to_string(num);
205 assert(callNode->arg_size() >= 1 &&
"strlen expects one argument");
206 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
212 ae->updateAbsValue(retVar, byteLen, callNode);
219 assert(callNode->arg_size() >= 4 &&
"recv expects four arguments");
221 const SVFVar* retVar = callNode->getRetICFGNode()->getActualRet();
222 ae->updateAbsValue(retVar, len, callNode);
229 assert(callNode->arg_size() >= 1 &&
"free expects one argument");
231 const AbstractValue& ptrVal =
ae->getAbsValue(callNode->getArgument(0), callNode);
239 std::vector<std::string> freeFunctions =
241 "VOS_MemFree",
"cfree",
"free",
"free_all_mem",
"freeaddrinfo",
242 "gcry_mpi_release",
"gcry_sexp_release",
"globfree",
"nhfree",
243 "obstack_free",
"safe_cfree",
"safe_free",
"safefree",
"safexfree",
244 "sm_free",
"vim_free",
"xfree",
"SSL_CTX_free",
"SSL_free",
"XFree"
247 for (
const auto&
name : freeFunctions)
255 return ae->getAbsState(node);
262 Set<std::string> buf_checkpoint_names = {
"UNSAFE_BUFACCESS",
"SAFE_BUFACCESS"};
265 for (
auto it =
svfir->getICFG()->begin(); it !=
svfir->getICFG()->end(); ++it)
270 if (
const FunObjVar *fun = call->getCalledFunction())
272 if (ae_checkpoint_names.find(fun->getName()) !=
273 ae_checkpoint_names.end())
279 if (buf_checkpoint_names.find(fun->getName()) !=
280 buf_checkpoint_names.end())
287 if (nullptr_checkpoint_names.find(fun->getName()) !=
288 nullptr_checkpoint_names.end())
320 for (
const auto &addr: expr0.
getAddrs())
340 assert(fun &&
"FunObjVar* is nullptr");
343 for (
const std::string &annotation:
ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
345 if (annotation.find(
"MEMCPY") != std::string::npos)
347 if (annotation.find(
"MEMSET") != std::string::npos)
349 if (annotation.find(
"STRCPY") != std::string::npos)
351 if (annotation.find(
"STRCAT") != std::string::npos)
370 else if (extType ==
MEMCPY)
375 else if (extType ==
MEMSET)
381 else if (extType ==
STRCPY)
385 else if (extType ==
STRCAT)
390 if (
name.find(
"ncat") != std::string::npos)
413 ->getTypeOfElement()->getByteSize();
417 assert(
false &&
"unsupported type for element size");
449 for (
const auto& addr : ptrVal.
getAddrs())
455 if (
svfir->getBaseObject(objId)->isConstantByteSize())
457 dst_size =
svfir->getBaseObject(objId)->getByteSizeOfObj();
461 const ICFGNode* icfgNode =
svfir->getBaseObject(objId)->getICFGNode();
466 dst_size =
ae->getAllocaInstByteSize(addrStmt).upperBound;
479 for (
const auto &addr: expr0.
getAddrs())
509 assert(
isValidLength(srcLen) &&
"getStrlen must return a bounded length");
521 assert(
isValidLength(dstLen) &&
"getStrlen must return a bounded length");
533 assert(
isValidLength(dstLen) &&
"getStrlen must return a bounded length");
546 u32_t range_val = size / elemSize;
554 for (
const auto &dstAddr: expr_dst.
getAddrs())
556 for (
const auto &srcAddr: expr_src.
getAddrs())
582 ->getTypeOfElement()->getByteSize();
590 assert(
false &&
"unsupported type for element size");
593 u32_t range_val = size / elemSize;
598 for (
const auto &addr: lhs_gep.
getAddrs())
609 as.
store(addr, elem);
635 if (intType->isSigned())
637 ub =
static_cast<s64_t>(std::numeric_limits<s32_t>::max());
638 lb =
static_cast<s64_t>(std::numeric_limits<s32_t>::min());
642 ub =
static_cast<s64_t>(std::numeric_limits<u32_t>::max());
643 lb =
static_cast<s64_t>(std::numeric_limits<u32_t>::min());
648 if (intType->isSigned())
650 ub =
static_cast<s64_t>(std::numeric_limits<s16_t>::max());
651 lb =
static_cast<s64_t>(std::numeric_limits<s16_t>::min());
655 ub =
static_cast<s64_t>(std::numeric_limits<u16_t>::max());
656 lb =
static_cast<s64_t>(std::numeric_limits<u16_t>::min());
661 if (intType->isSigned())
663 ub =
static_cast<s64_t>(std::numeric_limits<int8_t>::max());
664 lb =
static_cast<s64_t>(std::numeric_limits<int8_t>::min());
668 ub =
static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
669 lb =
static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
677 s64_t ub =
static_cast<s64_t>(std::numeric_limits<s32_t>::max());
678 s64_t lb =
static_cast<s64_t>(std::numeric_limits<s32_t>::min());
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
AbstractInterpretation * ae
Owning AbstractInterpretation; provides state access.
AbstractState & getAbsState(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
void initExtFunMap()
Initializes the external function map.
IntervalValue getStrlen(const ValVar *strValue, const ICFGNode *node)
Calculate the length of a null-terminated string in abstract state.
void handleMemcpy(const ValVar *dst, const ValVar *src, const IntervalValue &len, u32_t start_idx, const ICFGNode *node)
Core memcpy: copy len bytes from src to dst starting at dst[start_idx].
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
void handleStrncat(const CallICFGNode *call)
static bool isValidLength(const IntervalValue &len)
Check if an interval length is usable (not bottom, not unbounded).
Set< const CallICFGNode * > checkpoints
friend class AbstractInterpretation
std::string strRead(const ValVar *rhs, const ICFGNode *node)
Reads a string from the abstract state.
u32_t getElementSize(const ValVar *var)
Get the byte size of each element for a pointer/array variable.
void handleMemset(const ValVar *dst, const IntervalValue &elem, const IntervalValue &len, const ICFGNode *node)
AbsExtAPI(AbstractInterpretation *ae)
Constructor for AbsExtAPI.
SVFIR * svfir
Pointer to the SVF intermediate representation.
ExtAPIType
Enumeration of external API types.
static u32_t getBoundedMinimumByteCount(const IntervalValue &len)
Return the lower bound of len, capped by the field limit.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
ICFG * icfg
Pointer to the interprocedural control flow graph.
void handleStrcat(const CallICFGNode *call)
void handleStrcpy(const CallICFGNode *call)
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
u32_t getIDFromAddr(u32_t addr) const
Return the internal index if addr is an address otherwise return the value of idx.
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
static bool isNullOrBlackHoleAddr(u32_t addr)
Whether addr has no concrete backing memory object.
virtual AbstractValue & load(u32_t addr)
void addToFreedAddrs(NodeID addr)
void join_with(const AbstractValue &other)
IntervalValue & getInterval()
AddressValue & getAddrs()
bool is_minus_infinity() const
s64_t getIntNumeral() const
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
const FunObjVar * getCalledFunction() const
const RetICFGNode * getRetICFGNode() const
Return callsite.
static ExtAPI * getExtAPI()
const SVFStmtList & getSVFStmts() const
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
const BoundedInt & ub() const
Return the upper bound.
s64_t getIntNumeral() const
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
const std::string toString() const
void set_to_top()
Set current IntervalValue as top.
bool equals(const IntervalValue &other) const
Equality comparison.
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
const ValVar * getRHSVar() const
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
static const Option< bool > NullDerefCheck
nullptr dereference checker, Default: false
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
const SVFVar * getActualRet() const
Return actual return parameter.
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
virtual const SVFType * getType() const
virtual const std::string & getName() const
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::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
LLVM_NODISCARD bool isa(const Y &Val)
std::string errMsg(const std::string &msg)
Print error message by converting a string into red string output.
std::ostream & errs()
Overwrite llvm::errs().
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set