Static Value-Flow Analysis
Loading...
Searching...
No Matches
AbsExtAPI.cpp
Go to the documentation of this file.
1//===- AbsExtAPI.cpp -- Abstract Interpretation External API handler-----//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23
24//
25// Created on: Sep 9, 2024
26// Author: Xiao Cheng, Jiawei Wang
27//
28//
29#include "AE/Svfexe/AbsExtAPI.h"
31#include "WPA/Andersen.h"
32#include "Util/Options.h"
33
34using namespace SVF;
41
43{
44#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
45 auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
46 /* run real ext function */ \
47 AbstractState& as = getAbsStateFromTrace(callNode); \
48 u32_t rhs_id = callNode->getArgument(0)->getId(); \
49 if (!as.inVarToValTable(rhs_id)) return; \
50 u32_t rhs = as[rhs_id].getInterval().lb().getIntNumeral(); \
51 s32_t res = FUNC_NAME(rhs); \
52 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId(); \
53 as[lhsId] = IntervalValue(res); \
54 return; \
55 }; \
56 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
57
69 SSE_FUNC_PROCESS(llvm.sin.f64, sin);
70 SSE_FUNC_PROCESS(llvm.cos.f64, cos);
71 SSE_FUNC_PROCESS(llvm.tan.f64, tan);
72 SSE_FUNC_PROCESS(llvm.log.f64, log);
76
77 auto sse_svf_assert = [this](const CallICFGNode* callNode)
78 {
80 u32_t arg0 = callNode->getArgument(0)->getId();
82 if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
83 {
84 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
85 }
86 else
87 {
88 SVFUtil::errs() << SVFUtil::errMsg("Assertion failure, this svf_assert cannot be verified!!\n") << callNode->toString() << "\n";
89 assert(false);
90 }
91 return;
92 };
93 func_map["svf_assert"] = sse_svf_assert;
94
95 auto svf_assert_eq = [this](const CallICFGNode* callNode)
96 {
97 u32_t arg0 = callNode->getArgument(0)->getId();
98 u32_t arg1 = callNode->getArgument(1)->getId();
100 if (as[arg0].getInterval().equals(as[arg1].getInterval()))
101 {
102 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
103 }
104 else
105 {
106 SVFUtil::errs() <<"svf_assert_eq Fail. " << callNode->toString() << "\n";
107 assert(false);
108 }
109 return;
110 };
111 func_map["svf_assert_eq"] = svf_assert_eq;
112
113 auto svf_print = [&](const CallICFGNode* callNode)
114 {
115 if (callNode->arg_size() < 2) return;
117 u32_t num_id = callNode->getArgument(0)->getId();
118 std::string text = strRead(as, callNode->getArgument(1));
119 assert(as.inVarToValTable(num_id) && "print() should pass integer");
120 IntervalValue itv = as[num_id].getInterval();
121 std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
122 << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
123 return;
124 };
125 func_map["svf_print"] = svf_print;
126
127 auto svf_set_value = [&](const CallICFGNode* callNode)
128 {
129 if (callNode->arg_size() < 2) return;
131 AbstractValue& num = as[callNode->getArgument(0)->getId()];
132 AbstractValue& lb = as[callNode->getArgument(1)->getId()];
133 AbstractValue& ub = as[callNode->getArgument(2)->getId()];
135 num.getInterval().set_to_top();
136 num.getInterval().meet_with(IntervalValue(lb.getInterval().lb(), ub.getInterval().ub()));
137 const ICFGNode* node = SVFUtil::cast<ValVar>(callNode->getArgument(0))->getICFGNode();
138 for (const SVFStmt* stmt: node->getSVFStmts())
139 {
140 if (SVFUtil::isa<LoadStmt>(stmt))
141 {
142 const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
143 NodeID rhsId = load->getRHSVarID();
144 as.storeValue(rhsId, num);
145 }
146 }
147 return;
148 };
149 func_map["set_value"] = svf_set_value;
150
151 auto sse_scanf = [&](const CallICFGNode* callNode)
152 {
154 //scanf("%d", &data);
155 if (callNode->arg_size() < 2) return;
156
157 u32_t dst_id = callNode->getArgument(1)->getId();
158 if (!as.inVarToAddrsTable(dst_id))
159 {
160 return;
161 }
162 else
163 {
165 for (auto vaddr: Addrs.getAddrs())
166 {
167 u32_t objId = as.getIDFromAddr(vaddr);
169 as.store(vaddr, range);
170 }
171 }
172 };
173 auto sse_fscanf = [&](const CallICFGNode* callNode)
174 {
175 //fscanf(stdin, "%d", &data);
176 if (callNode->arg_size() < 3) return;
178 u32_t dst_id = callNode->getArgument(2)->getId();
179 if (!as.inVarToAddrsTable(dst_id))
180 {
181 }
182 else
183 {
185 for (auto vaddr: Addrs.getAddrs())
186 {
187 u32_t objId = as.getIDFromAddr(vaddr);
189 as.store(vaddr, range);
190 }
191 }
192 };
193
194 func_map["__isoc99_fscanf"] = sse_fscanf;
195 func_map["__isoc99_scanf"] = sse_scanf;
196 func_map["__isoc99_vscanf"] = sse_scanf;
197 func_map["fscanf"] = sse_fscanf;
198 func_map["scanf"] = sse_scanf;
199 func_map["sscanf"] = sse_scanf;
200 func_map["__isoc99_sscanf"] = sse_scanf;
201 func_map["vscanf"] = sse_scanf;
202
203 auto sse_fread = [&](const CallICFGNode *callNode)
204 {
205 if (callNode->arg_size() < 3) return;
207 u32_t block_count_id = callNode->getArgument(2)->getId();
208 u32_t block_size_id = callNode->getArgument(1)->getId();
210 IntervalValue block_size = as[block_size_id].getInterval();
212 };
213 func_map["fread"] = sse_fread;
214
215 auto sse_sprintf = [&](const CallICFGNode *callNode)
216 {
217 // printf is difficult to predict since it has no byte size arguments
218 };
219
220 auto sse_snprintf = [&](const CallICFGNode *callNode)
221 {
222 if (callNode->arg_size() < 2) return;
224 u32_t size_id = callNode->getArgument(1)->getId();
225 u32_t dst_id = callNode->getArgument(0)->getId();
226 // get elem size of arg2
227 u32_t elemSize = 1;
228 if (callNode->getArgument(2)->getType()->isArrayTy())
229 {
230 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
231 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
232 }
233 else if (callNode->getArgument(2)->getType()->isPointerTy())
234 {
235 elemSize = as.getPointeeElement(callNode->getArgument(2)->getId())->getByteSize();
236 }
237 else
238 {
239 return;
240 // assert(false && "we cannot support this type");
241 }
242 IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
243 if (!as.inVarToAddrsTable(dst_id))
244 {
245 }
246 };
247 func_map["__snprintf_chk"] = sse_snprintf;
248 func_map["__vsprintf_chk"] = sse_sprintf;
249 func_map["__sprintf_chk"] = sse_sprintf;
250 func_map["snprintf"] = sse_snprintf;
251 func_map["sprintf"] = sse_sprintf;
252 func_map["vsprintf"] = sse_sprintf;
253 func_map["vsnprintf"] = sse_snprintf;
254 func_map["__vsnprintf_chk"] = sse_snprintf;
255 func_map["swprintf"] = sse_snprintf;
256 func_map["_snwprintf"] = sse_snprintf;
257
258
259 auto sse_itoa = [&](const CallICFGNode* callNode)
260 {
261 // itoa(num, ch, 10);
262 // num: int, ch: char*, 10 is decimal
263 if (callNode->arg_size() < 3) return;
265 u32_t num_id = callNode->getArgument(0)->getId();
266
267 u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
268 std::string snum = std::to_string(num);
269 };
270 func_map["itoa"] = sse_itoa;
271
272
273 auto sse_strlen = [&](const CallICFGNode *callNode)
274 {
275 if (callNode->arg_size() < 1) return;
277 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
278 // strlen/wcslen return the number of characters (not bytes).
279 // getStrlen returns byte-scaled length (len * elemSize) for use
280 // by memcpy/strcpy. Here we need the raw character count, so
281 // divide back by elemSize.
282 IntervalValue byteLen = getStrlen(as, callNode->getArgument(0));
283 u32_t elemSize = getElementSize(as, callNode->getArgument(0));
284 if (byteLen.is_numeral() && elemSize > 1)
285 as[lhsId] = IntervalValue(byteLen.getIntNumeral() / (s64_t)elemSize);
286 else
287 as[lhsId] = byteLen;
288 };
289 func_map["strlen"] = sse_strlen;
290 func_map["wcslen"] = sse_strlen;
291
292 auto sse_recv = [&](const CallICFGNode *callNode)
293 {
294 // recv(sockfd, buf, len, flags);
295 if (callNode->arg_size() < 4) return;
297 u32_t len_id = callNode->getArgument(2)->getId();
298 IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
299 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
300 as[lhsId] = len;
301 };
302 func_map["recv"] = sse_recv;
303 func_map["__recv"] = sse_recv;
304
305 auto sse_free = [&](const CallICFGNode *callNode)
306 {
307 if (callNode->arg_size() < 1) return;
309 const u32_t freePtr = callNode->getArgument(0)->getId();
310 for (auto addr: as[freePtr].getAddrs())
311 {
313 {
314 // Detected a double free — the address has already been freed.
315 // No action is taken at this point.
316 }
317 else
318 {
319 as.addToFreedAddrs(addr);
320 }
321 }
322 };
323 // Add all free-related functions to func_map
324 std::vector<std::string> freeFunctions =
325 {
326 "VOS_MemFree", "cfree", "free", "free_all_mem", "freeaddrinfo",
327 "gcry_mpi_release", "gcry_sexp_release", "globfree", "nhfree",
328 "obstack_free", "safe_cfree", "safe_free", "safefree", "safexfree",
329 "sm_free", "vim_free", "xfree", "SSL_CTX_free", "SSL_free", "XFree"
330 };
331
332 for (const auto& name : freeFunctions)
333 {
335 }
336};
337
339{
340 if (abstractTrace.count(node) == 0)
341 {
342 assert(0 && "No preAbsTrace for this node");
343 abort();
344 }
345 else
346 {
347 return abstractTrace[node];
348 }
349}
350
352{
353 // sse read string nodeID->string
354 std::string str0;
355
357 {
358 // dead loop for string and break if there's a \0. If no \0, it will throw err.
359 if (!as.inVarToAddrsTable(rhs->getId())) continue;
361 as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
362
364 for (const auto &addr: expr0.getAddrs())
365 {
366 val.join_with(as.load(addr));
367 }
368 if (!val.getInterval().is_numeral())
369 {
370 break;
371 }
372 if ((char) val.getInterval().getIntNumeral() == '\0')
373 {
374 break;
375 }
376 str0.push_back((char) val.getInterval().getIntNumeral());
377 }
378 return str0;
379}
380
382{
384 const FunObjVar *fun = call->getCalledFunction();
385 assert(fun && "FunObjVar* is nullptr");
387 // get type of mem api
388 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
389 {
390 if (annotation.find("MEMCPY") != std::string::npos)
391 extType = MEMCPY;
392 if (annotation.find("MEMSET") != std::string::npos)
393 extType = MEMSET;
394 if (annotation.find("STRCPY") != std::string::npos)
395 extType = STRCPY;
396 if (annotation.find("STRCAT") != std::string::npos)
397 extType = STRCAT;
398 }
399 if (extType == UNCLASSIFIED)
400 {
401 if (func_map.find(fun->getName()) != func_map.end())
402 {
403 func_map[fun->getName()](call);
404 }
405 else
406 {
407 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
408 {
409 u32_t lhsId = ret->getId();
410 if (as.inVarToAddrsTable(lhsId))
411 {
412
413 }
414 else
415 {
417 }
418 }
419 return;
420 }
421 }
422 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
423 else if (extType == MEMCPY)
424 {
425 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
426 (void)svfir->getSVFVar(call->getArgument(0)->getId());
427 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
428 }
429 else if (extType == MEMSET)
430 {
431 // memset dst is arg0, elem is arg1, size is arg2
432 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
433 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
434 handleMemset(as, call->getArgument(0), elem, len);
435 }
436 else if (extType == STRCPY)
437 {
438 handleStrcpy(call);
439 }
440 else if (extType == STRCAT)
441 {
442 // Both strcat and strncat are annotated as STRCAT.
443 // Distinguish by name: strncat/wcsncat contain "ncat".
444 const std::string& name = fun->getName();
445 if (name.find("ncat") != std::string::npos)
446 handleStrncat(call);
447 else
448 handleStrcat(call);
449 }
450 else
451 {
452
453 }
454 return;
455}
456
457// ===----------------------------------------------------------------------===//
458// Shared primitives for string/memory handlers
459// ===----------------------------------------------------------------------===//
460
464{
465 if (var->getType()->isArrayTy())
466 {
467 return SVFUtil::dyn_cast<SVFArrayType>(var->getType())
468 ->getTypeOfElement()->getByteSize();
469 }
470 if (var->getType()->isPointerTy())
471 {
472 if (const SVFType* elemType = as.getPointeeElement(var->getId()))
473 {
474 if (elemType->isArrayTy())
475 return SVFUtil::dyn_cast<SVFArrayType>(elemType)
476 ->getTypeOfElement()->getByteSize();
477 return elemType->getByteSize();
478 }
479 return 1;
480 }
481 assert(false && "unsupported type for element size");
482 return 1;
483}
484
489{
490 return !len.isBottom() && !len.lb().is_minus_infinity();
491}
492
497{
498 NodeID value_id = strValue->getId();
499
500 // Step 1: determine the buffer size (in bytes) backing this pointer
501 u32_t dst_size = 0;
502 for (const auto& addr : as[value_id].getAddrs())
503 {
504 NodeID objId = as.getIDFromAddr(addr);
506 {
508 }
509 else
510 {
511 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
512 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
513 {
514 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
515 {
516 dst_size = as.getAllocaInstByteSize(addrStmt);
517 }
518 }
519 }
520 }
521
522 // Step 2: scan for '\0' terminator
523 u32_t len = 0;
524 if (as.inVarToAddrsTable(value_id))
525 {
526 for (u32_t index = 0; index < dst_size; index++)
527 {
529 as.getGepObjAddrs(value_id, IntervalValue(index));
531 for (const auto &addr: expr0.getAddrs())
532 {
533 val.join_with(as.load(addr));
534 }
535 if (val.getInterval().is_numeral() &&
536 (char) val.getInterval().getIntNumeral() == '\0')
537 {
538 break;
539 }
540 ++len;
541 }
542 }
543
544 // Step 3: scale by element size and return
546 if (len == 0)
548 return IntervalValue(len * elemSize);
549}
550
551// ===----------------------------------------------------------------------===//
552// String/memory operation handlers
553// ===----------------------------------------------------------------------===//
554
558{
560 const SVFVar* dst = call->getArgument(0);
561 const SVFVar* src = call->getArgument(1);
563 // no need to -1, since srcLen includes up to (but not past) '\0'
564 if (!isValidLength(srcLen)) return;
565 handleMemcpy(as, dst, src, srcLen, 0);
566}
567
571{
573 const SVFVar* dst = call->getArgument(0);
574 const SVFVar* src = call->getArgument(1);
577 if (!isValidLength(dstLen)) return;
578 handleMemcpy(as, dst, src, srcLen, dstLen.lb().getIntNumeral());
579}
580
584{
586 const SVFVar* dst = call->getArgument(0);
587 const SVFVar* src = call->getArgument(1);
588 IntervalValue n = as[call->getArgument(2)->getId()].getInterval();
590 if (!isValidLength(dstLen)) return;
591 handleMemcpy(as, dst, src, n, dstLen.lb().getIntNumeral());
592}
593
596 const SVF::SVFVar *src, IntervalValue len,
598{
599 if (!isValidLength(len)) return;
600
601 u32_t dstId = dst->getId();
602 u32_t srcId = src->getId();
604 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
605 (u32_t)len.lb().getIntNumeral());
606 u32_t range_val = size / elemSize;
607
608 if (!as.inVarToAddrsTable(srcId) || !as.inVarToAddrsTable(dstId))
609 return;
610
611 for (u32_t index = 0; index < range_val; index++)
612 {
614 as.getGepObjAddrs(srcId, IntervalValue(index));
616 as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
617 for (const auto &dstAddr: expr_dst.getAddrs())
618 {
619 for (const auto &srcAddr: expr_src.getAddrs())
620 {
621 u32_t objId = as.getIDFromAddr(srcAddr);
622 if (as.inAddrToValTable(objId) || as.inAddrToAddrsTable(objId))
623 {
624 as.store(dstAddr, as.load(srcAddr));
625 }
626 }
627 }
628 }
629}
630
638{
639 if (!isValidLength(len)) return;
640
641 u32_t dstId = dst->getId();
642 u32_t elemSize = 1;
643 if (dst->getType()->isArrayTy())
644 {
645 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())
646 ->getTypeOfElement()->getByteSize();
647 }
648 else if (dst->getType()->isPointerTy())
649 {
650 if (const SVFType* elemType = as.getPointeeElement(dstId))
651 elemSize = elemType->getByteSize();
652 else
653 elemSize = 1;
654 }
655 else
656 {
657 assert(false && "unsupported type for element size");
658 }
659 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
660 (u32_t)len.lb().getIntNumeral());
661 u32_t range_val = size / elemSize;
662
663 for (u32_t index = 0; index < range_val; index++)
664 {
665 if (!as.inVarToAddrsTable(dstId))
666 break;
667 AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
668 for (const auto &addr: lhs_gep.getAddrs())
669 {
670 u32_t objId = as.getIDFromAddr(addr);
671 if (as.inAddrToValTable(objId))
672 {
673 AbstractValue tmp = as.load(addr);
675 as.store(addr, tmp);
676 }
677 else
678 {
679 as.store(addr, elem);
680 }
681 }
682 }
683}
684
697{
698 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
699 {
700 u32_t bits = type->getByteSize() * 8;
701 s64_t ub = 0;
702 s64_t lb = 0;
703 if (bits >= 32)
704 {
705 if (intType->isSigned())
706 {
707 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
708 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
709 }
710 else
711 {
712 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
713 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
714 }
715 }
716 else if (bits == 16)
717 {
718 if (intType->isSigned())
719 {
720 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
721 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
722 }
723 else
724 {
725 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
726 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
727 }
728 }
729 else if (bits == 8)
730 {
731 if (intType->isSigned())
732 {
733 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
734 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
735 }
736 else
737 {
738 ub = static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
739 lb = static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
740 }
741 }
742 return IntervalValue(lb, ub);
743 }
744 else if (SVFUtil::isa<SVFOtherType>(type))
745 {
746 // handle other type like float double, set s32_t as the range
747 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
748 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
749 return IntervalValue(lb, ub);
750 }
751 else
752 {
753 return IntervalValue::top();
754 // other types, return top interval
755 }
756}
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
newitem type
Definition cJSON.cpp:2739
cJSON * n
Definition cJSON.cpp:2558
const char *const name
Definition cJSON.h:264
int index
Definition cJSON.h:170
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)
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:42
IntervalValue getStrlen(AbstractState &as, const SVF::SVFVar *strValue)
Calculate the length of a null-terminated string in abstract state.
Map< const ICFGNode *, AbstractState > & abstractTrace
Map of ICFG nodes to abstract states.
Definition AbsExtAPI.h:114
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).
AbsExtAPI(Map< const ICFGNode *, AbstractState > &traces)
Constructor for AbsExtAPI.
Definition AbsExtAPI.cpp:35
AbstractState & getAbsStateFromTrace(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
void handleMemcpy(AbstractState &as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
Core memcpy: copy len bytes from src to dst starting at dst[start_idx].
SVFIR * svfir
Pointer to the SVF intermediate representation.
Definition AbsExtAPI.h:112
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:113
void handleStrcat(const CallICFGNode *call)
void handleStrcpy(const CallICFGNode *call)
u32_t getElementSize(AbstractState &as, const SVFVar *var)
Get the byte size of each element for a pointer/array variable.
Map< std::string, std::function< void(const CallICFGNode *)> > func_map
Map of function names to handlers.
Definition AbsExtAPI.h:115
static AbstractInterpretation & getAEInstance()
Set< const CallICFGNode * > checkpoints
static bool isBlackHoleObjAddr(u32_t addr)
void join_with(const AbstractValue &other)
IntervalValue & getInterval()
NodeID getRHSVarID() const
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.
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:482
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:500
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:439
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:44
const std::vector< std::string > & getExtFuncAnnotations(const FunObjVar *fun)
Definition ExtAPI.cpp:256
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:115
const BoundedInt & ub() const
Return the upper bound.
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
const std::string toString() const
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
const BoundedInt & lb() const
Return the lower bound.
static const Option< u32_t > MaxFieldLimit
Maximum number of field derivations for an object.
Definition Options.h:35
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:624
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:478
ICFG * getICFG() const
Definition SVFIR.h:217
const SVFVar * getSVFVar(NodeID id) const
ObjVar/GepObjVar/BaseObjVar.
Definition SVFIR.h:131
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:116
bool isArrayTy() const
Definition SVFType.h:299
bool isPointerTy() const
Definition SVFType.h:294
NodeID getId() const
Get ID.
Definition SVFValue.h:160
virtual const SVFType * getType() const
Definition SVFValue.h:171
virtual const std::string & getName() const
Definition SVFValue.h:186
int iscntrl(int c)
Definition extapi.c:932
int isdigit(int c)
Definition extapi.c:937
int isgraph(int c)
Definition extapi.c:942
int isspace(char c)
Definition extapi.c:962
int isprint(int c)
Definition extapi.c:952
int ispunct(int argument)
Definition extapi.c:957
int isblank(int character)
Definition extapi.c:927
int isalnum(int character)
Definition extapi.c:917
int isupper(int c)
Definition extapi.c:967
int isxdigit(int c)
Definition extapi.c:972
int isalpha(int character)
Definition extapi.c:922
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 & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:58
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:47
signed long long s64_t
Definition GeneralType.h:50