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 = getAbstractState(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 {
79 checkpoints.erase(callNode);
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 // traverse every ICFGNode
354 Set<std::string> ae_checkpoint_names = {"svf_assert"};
355 Set<std::string> buf_checkpoint_names = {"UNSAFE_BUFACCESS", "SAFE_BUFACCESS"};
356 Set<std::string> nullptr_checkpoint_names = {"UNSAFE_LOAD", "SAFE_LOAD"};
357
358 for (auto it = svfir->getICFG()->begin(); it != svfir->getICFG()->end(); ++it)
359 {
360 const ICFGNode* node = it->second;
361 if (const CallICFGNode *call = SVFUtil::dyn_cast<CallICFGNode>(node))
362 {
363 if (const FunObjVar *fun = call->getCalledFunction())
364 {
365 if (ae_checkpoint_names.find(fun->getName()) !=
367 {
368 checkpoints.insert(call);
369 }
371 {
372 if (buf_checkpoint_names.find(fun->getName()) !=
374 {
375 checkpoints.insert(call);
376 }
377 }
379 {
380 if (nullptr_checkpoint_names.find(fun->getName()) !=
382 {
383 checkpoints.insert(call);
384 }
385 }
386 }
387 }
388 }
389}
390
392{
393 if (checkpoints.size() == 0)
394 {
395 return;
396 }
397 else
398 {
399 SVFUtil::errs() << SVFUtil::errMsg("At least one svf_assert has not been checked!!") << "\n";
400 for (const CallICFGNode* call: checkpoints)
401 SVFUtil::errs() << call->toString() + "\n";
402 assert(false);
403 }
404}
405
407{
408 // sse read string nodeID->string
409 std::string str0;
410
412 {
413 // dead loop for string and break if there's a \0. If no \0, it will throw err.
414 if (!as.inVarToAddrsTable(rhs->getId())) continue;
416 as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
417
419 for (const auto &addr: expr0.getAddrs())
420 {
421 val.join_with(as.load(addr));
422 }
423 if (!val.getInterval().is_numeral())
424 {
425 break;
426 }
427 if ((char) val.getInterval().getIntNumeral() == '\0')
428 {
429 break;
430 }
431 str0.push_back((char) val.getInterval().getIntNumeral());
432 }
433 return str0;
434}
435
437{
439 const FunObjVar *fun = call->getCalledFunction();
440 assert(fun && "FunObjVar* is nullptr");
442 // get type of mem api
443 for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
444 {
445 if (annotation.find("MEMCPY") != std::string::npos)
446 extType = MEMCPY;
447 if (annotation.find("MEMSET") != std::string::npos)
448 extType = MEMSET;
449 if (annotation.find("STRCPY") != std::string::npos)
450 extType = STRCPY;
451 if (annotation.find("STRCAT") != std::string::npos)
452 extType = STRCAT;
453 }
454 if (extType == UNCLASSIFIED)
455 {
456 if (func_map.find(fun->getName()) != func_map.end())
457 {
458 func_map[fun->getName()](call);
459 }
460 else
461 {
462 if (const SVFVar* ret = call->getRetICFGNode()->getActualRet())
463 {
464 u32_t lhsId = ret->getId();
465 if (as.inVarToAddrsTable(lhsId))
466 {
467
468 }
469 else
470 {
472 }
473 }
474 return;
475 }
476 }
477 // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
478 else if (extType == MEMCPY)
479 {
480 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
481 (void)svfir->getSVFVar(call->getArgument(0)->getId());
482 handleMemcpy(as, call->getArgument(0), call->getArgument(1), len, 0);
483 }
484 else if (extType == MEMSET)
485 {
486 // memset dst is arg0, elem is arg1, size is arg2
487 IntervalValue len = as[call->getArgument(2)->getId()].getInterval();
488 IntervalValue elem = as[call->getArgument(1)->getId()].getInterval();
489 handleMemset(as, call->getArgument(0), elem, len);
490 }
491 else if (extType == STRCPY)
492 {
493 handleStrcpy(call);
494 }
495 else if (extType == STRCAT)
496 {
497 // Both strcat and strncat are annotated as STRCAT.
498 // Distinguish by name: strncat/wcsncat contain "ncat".
499 const std::string& name = fun->getName();
500 if (name.find("ncat") != std::string::npos)
501 handleStrncat(call);
502 else
503 handleStrcat(call);
504 }
505 else
506 {
507
508 }
509 return;
510}
511
512// ===----------------------------------------------------------------------===//
513// Shared primitives for string/memory handlers
514// ===----------------------------------------------------------------------===//
515
519{
520 if (var->getType()->isArrayTy())
521 {
522 return SVFUtil::dyn_cast<SVFArrayType>(var->getType())
523 ->getTypeOfElement()->getByteSize();
524 }
525 if (var->getType()->isPointerTy())
526 {
527 if (const SVFType* elemType = as.getPointeeElement(var->getId()))
528 {
529 if (elemType->isArrayTy())
530 return SVFUtil::dyn_cast<SVFArrayType>(elemType)
531 ->getTypeOfElement()->getByteSize();
532 return elemType->getByteSize();
533 }
534 return 1;
535 }
536 assert(false && "unsupported type for element size");
537 return 1;
538}
539
544{
545 return !len.isBottom() && !len.lb().is_minus_infinity();
546}
547
552{
553 NodeID value_id = strValue->getId();
554
555 // Step 1: determine the buffer size (in bytes) backing this pointer
556 u32_t dst_size = 0;
557 for (const auto& addr : as[value_id].getAddrs())
558 {
559 NodeID objId = as.getIDFromAddr(addr);
561 {
563 }
564 else
565 {
566 const ICFGNode* icfgNode = svfir->getBaseObject(objId)->getICFGNode();
567 for (const SVFStmt* stmt2: icfgNode->getSVFStmts())
568 {
569 if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
570 {
571 dst_size = as.getAllocaInstByteSize(addrStmt);
572 }
573 }
574 }
575 }
576
577 // Step 2: scan for '\0' terminator
578 u32_t len = 0;
579 if (as.inVarToAddrsTable(value_id))
580 {
581 for (u32_t index = 0; index < dst_size; index++)
582 {
584 as.getGepObjAddrs(value_id, IntervalValue(index));
586 for (const auto &addr: expr0.getAddrs())
587 {
588 val.join_with(as.load(addr));
589 }
590 if (val.getInterval().is_numeral() &&
591 (char) val.getInterval().getIntNumeral() == '\0')
592 {
593 break;
594 }
595 ++len;
596 }
597 }
598
599 // Step 3: scale by element size and return
601 if (len == 0)
603 return IntervalValue(len * elemSize);
604}
605
606// ===----------------------------------------------------------------------===//
607// String/memory operation handlers
608// ===----------------------------------------------------------------------===//
609
613{
615 const SVFVar* dst = call->getArgument(0);
616 const SVFVar* src = call->getArgument(1);
618 // no need to -1, since srcLen includes up to (but not past) '\0'
619 if (!isValidLength(srcLen)) return;
620 handleMemcpy(as, dst, src, srcLen, 0);
621}
622
626{
628 const SVFVar* dst = call->getArgument(0);
629 const SVFVar* src = call->getArgument(1);
632 if (!isValidLength(dstLen)) return;
633 handleMemcpy(as, dst, src, srcLen, dstLen.lb().getIntNumeral());
634}
635
639{
641 const SVFVar* dst = call->getArgument(0);
642 const SVFVar* src = call->getArgument(1);
643 IntervalValue n = as[call->getArgument(2)->getId()].getInterval();
645 if (!isValidLength(dstLen)) return;
646 handleMemcpy(as, dst, src, n, dstLen.lb().getIntNumeral());
647}
648
651 const SVF::SVFVar *src, IntervalValue len,
653{
654 if (!isValidLength(len)) return;
655
656 u32_t dstId = dst->getId();
657 u32_t srcId = src->getId();
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 if (!as.inVarToAddrsTable(srcId) || !as.inVarToAddrsTable(dstId))
664 return;
665
666 for (u32_t index = 0; index < range_val; index++)
667 {
669 as.getGepObjAddrs(srcId, IntervalValue(index));
671 as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
672 for (const auto &dstAddr: expr_dst.getAddrs())
673 {
674 for (const auto &srcAddr: expr_src.getAddrs())
675 {
676 u32_t objId = as.getIDFromAddr(srcAddr);
677 if (as.inAddrToValTable(objId) || as.inAddrToAddrsTable(objId))
678 {
679 as.store(dstAddr, as.load(srcAddr));
680 }
681 }
682 }
683 }
684}
685
693{
694 if (!isValidLength(len)) return;
695
696 u32_t dstId = dst->getId();
697 u32_t elemSize = 1;
698 if (dst->getType()->isArrayTy())
699 {
700 elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())
701 ->getTypeOfElement()->getByteSize();
702 }
703 else if (dst->getType()->isPointerTy())
704 {
705 if (const SVFType* elemType = as.getPointeeElement(dstId))
706 elemSize = elemType->getByteSize();
707 else
708 elemSize = 1;
709 }
710 else
711 {
712 assert(false && "unsupported type for element size");
713 }
714 u32_t size = std::min((u32_t)Options::MaxFieldLimit(),
715 (u32_t)len.lb().getIntNumeral());
716 u32_t range_val = size / elemSize;
717
718 for (u32_t index = 0; index < range_val; index++)
719 {
720 if (!as.inVarToAddrsTable(dstId))
721 break;
722 AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
723 for (const auto &addr: lhs_gep.getAddrs())
724 {
725 u32_t objId = as.getIDFromAddr(addr);
726 if (as.inAddrToValTable(objId))
727 {
728 AbstractValue tmp = as.load(addr);
730 as.store(addr, tmp);
731 }
732 else
733 {
734 as.store(addr, elem);
735 }
736 }
737 }
738}
739
752{
753 if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
754 {
755 u32_t bits = type->getByteSize() * 8;
756 s64_t ub = 0;
757 s64_t lb = 0;
758 if (bits >= 32)
759 {
760 if (intType->isSigned())
761 {
762 ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
763 lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
764 }
765 else
766 {
767 ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
768 lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
769 }
770 }
771 else if (bits == 16)
772 {
773 if (intType->isSigned())
774 {
775 ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
776 lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
777 }
778 else
779 {
780 ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
781 lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
782 }
783 }
784 else if (bits == 8)
785 {
786 if (intType->isSigned())
787 {
788 ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
789 lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
790 }
791 else
792 {
793 ub = static_cast<s64_t>(std::numeric_limits<uint8_t>::max());
794 lb = static_cast<s64_t>(std::numeric_limits<uint8_t>::min());
795 }
796 }
797 return IntervalValue(lb, ub);
798 }
799 else if (SVFUtil::isa<SVFOtherType>(type))
800 {
801 // handle other type like float double, set s32_t as the range
802 s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
803 s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
804 return IntervalValue(lb, ub);
805 }
806 else
807 {
808 return IntervalValue::top();
809 // other types, return top interval
810 }
811}
#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 collectCheckPoint()
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:119
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
Set< const CallICFGNode * > checkpoints
Definition AbsExtAPI.h:114
void checkPointAllSet()
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:117
ExtAPIType
Enumeration of external API types.
Definition AbsExtAPI.h:50
AbstractState & getAbstractState(const ICFGNode *node)
Retrieves the abstract state from the trace for a given ICFG node.
IntervalValue getRangeLimitFromType(const SVFType *type)
Gets the range limit from a type.
ICFG * icfg
Pointer to the interprocedural control flow graph.
Definition AbsExtAPI.h:118
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:120
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
iterator begin()
Iterators.
virtual const std::string toString() const
Definition ICFG.cpp:49
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
static const Option< bool > NullDerefCheck
nullptr dereference checker, Default: false
Definition Options.h:254
static const Option< bool > BufferOverflowCheck
buffer overflow checker, Default: false
Definition Options.h:252
const SVFVar * getActualRet() const
Return actual return parameter.
Definition ICFGNode.h:624
const BaseObjVar * getBaseObject(NodeID id) const
Definition SVFIR.h:488
ICFG * getICFG() const
Definition SVFIR.h:227
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