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 by Jiawei Wang on 2024/9/9.
26//
27#include "AE/Svfexe/AbsExtAPI.h"
29
30using namespace SVF;
37
39{
40#define SSE_FUNC_PROCESS(LLVM_NAME ,FUNC_NAME) \
41 auto sse_##FUNC_NAME = [this](const CallICFGNode *callNode) { \
42 /* run real ext function */ \
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); \
50 return; \
51 }; \
52 func_map[#FUNC_NAME] = sse_##FUNC_NAME;
53
65 SSE_FUNC_PROCESS(llvm.sin.f64, sin);
66 SSE_FUNC_PROCESS(llvm.cos.f64, cos);
67 SSE_FUNC_PROCESS(llvm.tan.f64, tan);
68 SSE_FUNC_PROCESS(llvm.log.f64, log);
72
73 auto sse_svf_assert = [this](const CallICFGNode* callNode)
74 {
76 u32_t arg0 = callNode->getArgument(0)->getId();
78 if (as[arg0].getInterval().equals(IntervalValue(1, 1)))
79 {
80 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
81 }
82 else
83 {
84 SVFUtil::errs() <<"svf_assert Fail. " << callNode->toString() << "\n";
85 assert(false);
86 }
87 return;
88 };
89 func_map["svf_assert"] = sse_svf_assert;
90
91 auto svf_assert_eq = [this](const CallICFGNode* callNode)
92 {
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()))
97 {
98 SVFUtil::errs() << SVFUtil::sucMsg("The assertion is successfully verified!!\n");
99 }
100 else
101 {
102 SVFUtil::errs() <<"svf_assert_eq Fail. " << callNode->toString() << "\n";
103 assert(false);
104 }
105 return;
106 };
107 func_map["svf_assert_eq"] = svf_assert_eq;
108
109 auto svf_print = [&](const CallICFGNode* callNode)
110 {
111 if (callNode->arg_size() < 2) return;
113 u32_t num_id = callNode->getArgument(0)->getId();
114 std::string text = strRead(as, callNode->getArgument(1));
115 assert(as.inVarToValTable(num_id) && "print() should pass integer");
116 IntervalValue itv = as[num_id].getInterval();
117 std::cout << "Text: " << text <<", Value: " << callNode->getArgument(0)->toString()
118 << ", PrintVal: " << itv.toString() << ", Loc:" << callNode->getSourceLoc() << std::endl;
119 return;
120 };
121 func_map["svf_print"] = svf_print;
122
123 auto svf_set_value = [&](const CallICFGNode* callNode)
124 {
125 if (callNode->arg_size() < 2) return;
127 AbstractValue& num = as[callNode->getArgument(0)->getId()];
128 AbstractValue& lb = as[callNode->getArgument(1)->getId()];
129 AbstractValue& ub = as[callNode->getArgument(2)->getId()];
131 num.getInterval().set_to_top();
132 num.getInterval().meet_with(IntervalValue(lb.getInterval().lb(), ub.getInterval().ub()));
133 const ICFGNode* node = SVFUtil::cast<ValVar>(callNode->getArgument(0))->getICFGNode();
134 for (const SVFStmt* stmt: node->getSVFStmts())
135 {
136 if (SVFUtil::isa<LoadStmt>(stmt))
137 {
138 const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
139 NodeID rhsId = load->getRHSVarID();
140 as.storeValue(rhsId, num);
141 }
142 }
143 return;
144 };
145 func_map["set_value"] = svf_set_value;
146
147 auto sse_scanf = [&](const CallICFGNode* callNode)
148 {
150 //scanf("%d", &data);
151 if (callNode->arg_size() < 2) return;
152
153 u32_t dst_id = callNode->getArgument(1)->getId();
154 if (!as.inVarToAddrsTable(dst_id))
155 {
156 return;
157 }
158 else
159 {
161 for (auto vaddr: Addrs.getAddrs())
162 {
165 as.store(vaddr, range);
166 }
167 }
168 };
169 auto sse_fscanf = [&](const CallICFGNode* callNode)
170 {
171 //fscanf(stdin, "%d", &data);
172 if (callNode->arg_size() < 3) return;
174 u32_t dst_id = callNode->getArgument(2)->getId();
175 if (!as.inVarToAddrsTable(dst_id))
176 {
177 }
178 else
179 {
181 for (auto vaddr: Addrs.getAddrs())
182 {
185 as.store(vaddr, range);
186 }
187 }
188 };
189
190 func_map["__isoc99_fscanf"] = sse_fscanf;
191 func_map["__isoc99_scanf"] = sse_scanf;
192 func_map["__isoc99_vscanf"] = sse_scanf;
193 func_map["fscanf"] = sse_fscanf;
194 func_map["scanf"] = sse_scanf;
195 func_map["sscanf"] = sse_scanf;
196 func_map["__isoc99_sscanf"] = sse_scanf;
197 func_map["vscanf"] = sse_scanf;
198
199 auto sse_fread = [&](const CallICFGNode *callNode)
200 {
201 if (callNode->arg_size() < 3) return;
203 u32_t block_count_id = callNode->getArgument(2)->getId();
204 u32_t block_size_id = callNode->getArgument(1)->getId();
206 IntervalValue block_size = as[block_size_id].getInterval();
208 };
209 func_map["fread"] = sse_fread;
210
211 auto sse_sprintf = [&](const CallICFGNode *callNode)
212 {
213 // printf is difficult to predict since it has no byte size arguments
214 };
215
216 auto sse_snprintf = [&](const CallICFGNode *callNode)
217 {
218 if (callNode->arg_size() < 2) return;
220 u32_t size_id = callNode->getArgument(1)->getId();
221 u32_t dst_id = callNode->getArgument(0)->getId();
222 // get elem size of arg2
223 u32_t elemSize = 1;
224 if (callNode->getArgument(2)->getType()->isArrayTy())
225 {
226 elemSize = SVFUtil::dyn_cast<SVFArrayType>(
227 callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
228 }
229 else if (callNode->getArgument(2)->getType()->isPointerTy())
230 {
231 elemSize = as.getPointeeElement(callNode->getArgument(2)->getId())->getByteSize();
232 }
233 else
234 {
235 return;
236 // assert(false && "we cannot support this type");
237 }
238 IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
239 if (!as.inVarToAddrsTable(dst_id))
240 {
241 }
242 };
243 func_map["__snprintf_chk"] = sse_snprintf;
244 func_map["__vsprintf_chk"] = sse_sprintf;
245 func_map["__sprintf_chk"] = sse_sprintf;
246 func_map["snprintf"] = sse_snprintf;
247 func_map["sprintf"] = sse_sprintf;
248 func_map["vsprintf"] = sse_sprintf;
249 func_map["vsnprintf"] = sse_snprintf;
250 func_map["__vsnprintf_chk"] = sse_snprintf;
251 func_map["swprintf"] = sse_snprintf;
252 func_map["_snwprintf"] = sse_snprintf;
253
254
255 auto sse_itoa = [&](const CallICFGNode* callNode)
256 {
257 // itoa(num, ch, 10);
258 // num: int, ch: char*, 10 is decimal
259 if (callNode->arg_size() < 3) return;
261 u32_t num_id = callNode->getArgument(0)->getId();
262
263 u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
264 std::string snum = std::to_string(num);
265 };
266 func_map["itoa"] = sse_itoa;
267
268
269 auto sse_strlen = [&](const CallICFGNode *callNode)
270 {
271 // check the arg size
272 if (callNode->arg_size() < 1) return;
273 const SVFVar* strValue = callNode->getArgument(0);
275 NodeID value_id = strValue->getId();
276 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
277 u32_t dst_size = 0;
278 for (const auto& addr : as[value_id].getAddrs())
279 {
282 {
284 }
285 else
286 {
287 const ICFGNode* addrNode = SVFUtil::cast<ICFGNode>(svfir->getBaseObj(objId)->getGNode());
288 for (const SVFStmt* stmt2: addrNode->getSVFStmts())
289 {
290 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
291 {
292 dst_size = as.getAllocaInstByteSize(addrStmt);
293 }
294 }
295 }
296 }
297 u32_t len = 0;
298 NodeID dstid = strValue->getId();
299 if (as.inVarToAddrsTable(dstid))
300 {
301 for (u32_t index = 0; index < dst_size; index++)
302 {
304 as.getGepObjAddrs(dstid, IntervalValue(index));
306 for (const auto &addr: expr0.getAddrs())
307 {
308 val.join_with(as.load(addr));
309 }
310 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
311 {
312 break;
313 }
314 ++len;
315 }
316 }
317 if (len == 0)
318 {
320 }
321 else
322 {
324 }
325 };
326 func_map["strlen"] = sse_strlen;
327 func_map["wcslen"] = sse_strlen;
328
329 auto sse_recv = [&](const CallICFGNode *callNode)
330 {
331 // recv(sockfd, buf, len, flags);
332 if (callNode->arg_size() < 4) return;
334 u32_t len_id = callNode->getArgument(2)->getId();
335 IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
336 u32_t lhsId = callNode->getRetICFGNode()->getActualRet()->getId();
337 as[lhsId] = len;
338 };
339 func_map["recv"] = sse_recv;
340 func_map["__recv"] = sse_recv;
341};
342
344{
345 const ICFGNode* repNode = icfg->getRepNode(node);
346 if (abstractTrace.count(repNode) == 0)
347 {
348 assert(0 && "No preAbsTrace for this node");
349 }
350 else
351 {
352 return abstractTrace[repNode];
353 }
354}
355
357{
358 // sse read string nodeID->string
359 std::string str0;
360
362 {
363 // dead loop for string and break if there's a \0. If no \0, it will throw err.
364 if (!as.inVarToAddrsTable(rhs->getId())) continue;
366 as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
367
369 for (const auto &addr: expr0.getAddrs())
370 {
371 val.join_with(as.load(addr));
372 }
373 if (!val.getInterval().is_numeral())
374 {
375 break;
376 }
377 if ((char) val.getInterval().getIntNumeral() == '\0')
378 {
379 break;
380 }
381 str0.push_back((char) val.getInterval().getIntNumeral());
382 }
383 return str0;
384}
385
387{
389 const SVFFunction *fun = call->getCalledFunction();
390 assert(fun && "SVFFunction* is nullptr");
392 // get type of mem api
393 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
394 {
395 if (annotation.find("MEMCPY") != std::string::npos)
396 extType = MEMCPY;
397 if (annotation.find("MEMSET") != std::string::npos)
398 extType = MEMSET;
399 if (annotation.find("STRCPY") != std::string::npos)
400 extType = STRCPY;
401 if (annotation.find("STRCAT") != std::string::npos)
402 extType = STRCAT;
403 }
404 if (extType == UNCLASSIFIED)
405 {
406 if (func_map.find(fun->getName()) != func_map.end())
407 {
408 func_map[fun->getName()](call);
409 }
410 else
411 {
412 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
413 {
414 u32_t lhsId = ret->getId();
415 if (as.inVarToAddrsTable(lhsId))
416 {
417
418 }
419 else
420 {
422 }
423 }
424 return;
425 }
426 }
427 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
428 else if (extType == MEMCPY)
429 {
430 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
431 svfir->getGNode(call->getArgument(0)->getId());
432 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
433 }
434 else if (extType == MEMSET)
435 {
436 // memset dst is arg0, elem is arg1, size is arg2
437 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
438 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
439 handleMemset(as, call->getArgument(0), elem, len);
440 }
441 else if (extType == STRCPY)
442 {
443 handleStrcpy(call);
444 }
445 else if (extType == STRCAT)
446 {
447 handleStrcat(call);
448 }
449 else
450 {
451
452 }
453 return;
454}
455
457{
458 // strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
459 // get the dst and src
461 const SVFVar* arg0Val = call->getArgument(0);
462 const SVFVar* arg1Val = call->getArgument(1);
464 // no need to -1, since it has \0 as the last byte
465 handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
466}
467
469{
470 NodeID value_id = strValue->getId();
471 u32_t dst_size = 0;
472 for (const auto& addr : as[value_id].getAddrs())
473 {
476 {
478 }
479 else
480 {
481 const ICFGNode* icfgNode = SVFUtil::cast<ICFGNode>( svfir->getBaseObj(objId)->getGNode());
482 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
483 {
484 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
485 {
486 dst_size = as.getAllocaInstByteSize(addrStmt);
487 }
488 }
489 }
490 }
491 u32_t len = 0;
492 u32_t elemSize = 1;
493 if (as.inVarToAddrsTable(value_id))
494 {
495 for (u32_t index = 0; index < dst_size; index++)
496 {
498 as.getGepObjAddrs(value_id, IntervalValue(index));
500 for (const auto &addr: expr0.getAddrs())
501 {
502 val.join_with(as.load(addr));
503 }
504 if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
505 {
506 break;
507 }
508 ++len;
509 }
510 if (strValue->getType()->isArrayTy())
511 {
512 elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
513 }
514 else if (strValue->getType()->isPointerTy())
515 {
516 if (const SVFType* elemType = as.getPointeeElement(value_id))
517 {
518 if (elemType->isArrayTy())
519 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
520 else
521 elemSize = elemType->getByteSize();
522 }
523 else
524 {
525 elemSize = 1;
526 }
527 }
528 else
529 {
530 assert(false && "we cannot support this type");
531 }
532 }
533 if (len == 0)
534 {
536 }
537 else
538 {
539 return IntervalValue(len * elemSize);
540 }
541}
542
543
545{
546 // __strcat_chk, strcat, __wcscat_chk, wcscat, __strncat_chk, strncat, __wcsncat_chk, wcsncat
547 // to check it is strcat group or strncat group
549 const SVFFunction *fun = call->getCalledFunction();
550 const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
551 const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
552 if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
553 {
554 const SVFVar* arg0Val = call->getArgument(0);
555 const SVFVar* arg1Val = call->getArgument(1);
559 handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
560 // do memcpy
561 }
562 else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
563 {
564 const SVFVar* arg0Val = call->getArgument(0);
565 const SVFVar* arg1Val = call->getArgument(1);
566 const SVFVar* arg2Val = call->getArgument(2);
567 IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
570 handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
571 // do memcpy
572 }
573 else
574 {
575 assert(false && "unknown strcat function, please add it to strcatGroup or strncatGroup");
576 }
577}
578
580{
581 u32_t dstId = dst->getId(); // pts(dstId) = {objid} objbar objtypeinfo->getType().
582 u32_t srcId = src->getId();
583 u32_t elemSize = 1;
584 if (dst->getType()->isArrayTy())
585 {
586 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
587 }
588 // memcpy(i32*, i32*, 40)
589 else if (dst->getType()->isPointerTy())
590 {
591 if (const SVFType* elemType = as.getPointeeElement(dstId))
592 {
593 if (elemType->isArrayTy())
594 elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
595 else
596 elemSize = elemType->getByteSize();
597 }
598 else
599 {
600 elemSize = 1;
601 }
602 }
603 else
604 {
605 assert(false && "we cannot support this type");
606 }
607 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
608 u32_t range_val = size / elemSize;
609 if (as.inVarToAddrsTable(srcId) && as.inVarToAddrsTable(dstId))
610 {
611 for (u32_t index = 0; index < range_val; index++)
612 {
613 // dead loop for string and break if there's a \0. If no \0, it will throw err.
615 as.getGepObjAddrs(srcId, IntervalValue(index));
617 as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
618 for (const auto &dst: expr_dst.getAddrs())
619 {
620 for (const auto &src: expr_src.getAddrs())
621 {
623 if (as.inAddrToValTable(objId))
624 {
625 as.store(dst, as.load(src));
626 }
627 else if (as.inAddrToAddrsTable(objId))
628 {
629 as.store(dst, as.load(src));
630 }
631 }
632 }
633 }
634 }
635}
636
638{
639 u32_t dstId = dst->getId();
640 u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
641 u32_t elemSize = 1;
642 if (dst->getType()->isArrayTy())
643 {
644 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
645 }
646 else if (dst->getType()->isPointerTy())
647 {
648 if (const SVFType* elemType = as.getPointeeElement(dstId))
649 {
650 elemSize = elemType->getByteSize();
651 }
652 else
653 {
654 elemSize = 1;
655 }
656 }
657 else
658 {
659 assert(false && "we cannot support this type");
660 }
661
662 u32_t range_val = size / elemSize;
663 for (u32_t index = 0; index < range_val; index++)
664 {
665 // dead loop for string and break if there's a \0. If no \0, it will throw err.
666 if (as.inVarToAddrsTable(dstId))
667 {
668 AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
669 for (const auto &addr: lhs_gep.getAddrs())
670 {
672 if (as.inAddrToValTable(objId))
673 {
674 AbstractValue tmp = as.load(addr);
676 as.store(addr, tmp);
677 }
678 else
679 {
680 as.store(addr, elem);
681 }
682 }
683 }
684 else
685 break;
686 }
687}
688
701{
702 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
703 {
704 u32_t bits = type->getByteSize() * 8;
705 s64_t ub = 0;
706 s64_t lb = 0;
707 if (bits >= 32)
708 {
709 if (intType->isSigned())
710 {
711 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
712 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
713 }
714 else
715 {
716 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
717 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
718 }
719 }
720 else if (bits == 16)
721 {
722 if (intType->isSigned())
723 {
724 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
725 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
726 }
727 else
728 {
729 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
730 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
731 }
732 }
733 else if (bits == 8)
734 {
735 if (intType->isSigned())
736 {
737 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
738 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
739 }
740 else
741 {
742 ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
743 lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
744 }
745 }
746 return IntervalValue(lb, ub);
747 }
748 else if (SVFUtil::isa<SVFOtherType>(type))
749 {
750 // handle other type like float double, set s32_t as the range
751 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
752 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
753 return IntervalValue(lb, ub);
754 }
755 else
756 {
757 return IntervalValue::top();
758 // other types, return top interval
759 }
760}
761
#define SSE_FUNC_PROCESS(LLVM_NAME,FUNC_NAME)
newitem type
Definition cJSON.cpp:2739
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)
Handles the memset API call.
void initExtFunMap()
Initializes the external function map.
Definition AbsExtAPI.cpp:38
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.
Definition AbsExtAPI.h:143
void handleExtAPI(const CallICFGNode *call)
Handles an external API call.
AbsExtAPI(Map< const ICFGNode *, AbstractState > &traces)
Constructor for AbsExtAPI.
Definition AbsExtAPI.cpp:31
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.
Definition AbsExtAPI.h:141
void handleStrcat(const SVF::CallICFGNode *call)
Handles the strcat API call.
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:52
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:142
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.
Definition AbsExtAPI.h:144
static AbstractInterpretation & getAEInstance()
Set< const CallICFGNode * > checkpoints
static u32_t getInternalID(u32_t idx)
Return the internal index if idx is an address otherwise return the value of idx.
void join_with(const AbstractValue &other)
IntervalValue & getInterval()
NodeID getRHSVarID() const
const ValVar * getArgument(u32_t ArgNo) const
Parameter operations.
Definition ICFGNode.h:500
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:457
const SVFFunction * getCalledFunction() const
Definition ICFGNode.h:518
const std::vector< std::string > & getExtFuncAnnotations(const SVFFunction *fun)
Definition ExtAPI.cpp:196
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:42
bool hasGNode(NodeID id) const
Has a node.
NodeType * getGNode(NodeID id) const
Get a node.
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:117
const ICFGNode * getRepNode(const ICFGNode *node) const
Definition ICFG.h:246
NodeID getValueNode(const SVFValue *V)
Definition IRGraph.h:137
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.
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.
Definition Options.h:38
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:627
NodeID getId() const
Get ID.
const MemObj * getBaseObj(NodeID id) const
Definition SVFIR.h:481
ICFG * getICFG() const
Definition SVFIR.h:172
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:254
bool isPointerTy() const
Definition SVFType.h:249
const std::string & getName() const
Definition SVFValue.h:243
virtual const SVFType * getType() const
Return type of the value.
int iscntrl(int c)
Definition extapi.c:846
int isdigit(int c)
Definition extapi.c:851
int isgraph(int c)
Definition extapi.c:856
int isspace(char c)
Definition extapi.c:876
int isprint(int c)
Definition extapi.c:866
int ispunct(int argument)
Definition extapi.c:871
int isblank(int character)
Definition extapi.c:841
int isalnum(int character)
Definition extapi.c:831
int isupper(int c)
Definition extapi.c:881
int isxdigit(int c)
Definition extapi.c:886
int isalpha(int character)
Definition extapi.c:836
std::string sucMsg(const std::string &msg)
Returns successful message by converting a string into green string output.
Definition SVFUtil.cpp:54
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49