svf-tools 1.0.987 → 1.0.989

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,765 @@
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"
28
+ #include "AE/Svfexe/AbstractInterpretation.h"
29
+
30
+ using namespace SVF;
31
+ AbsExtAPI::AbsExtAPI(Map<const ICFGNode*, AbstractState>& traces): abstractTrace(traces)
32
+ {
33
+ svfir = PAG::getPAG();
34
+ icfg = svfir->getICFG();
35
+ initExtFunMap();
36
+ }
37
+
38
+ void AbsExtAPI::initExtFunMap()
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 = svfir->getValueNode(callNode->getArgument(0)); \
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 = svfir->getValueNode(callNode->getCallSite()); \
49
+ as[lhsId] = IntervalValue(res); \
50
+ return; \
51
+ }; \
52
+ func_map[#FUNC_NAME] = sse_##FUNC_NAME;
53
+
54
+ SSE_FUNC_PROCESS(isalnum, isalnum);
55
+ SSE_FUNC_PROCESS(isalpha, isalpha);
56
+ SSE_FUNC_PROCESS(isblank, isblank);
57
+ SSE_FUNC_PROCESS(iscntrl, iscntrl);
58
+ SSE_FUNC_PROCESS(isdigit, isdigit);
59
+ SSE_FUNC_PROCESS(isgraph, isgraph);
60
+ SSE_FUNC_PROCESS(isprint, isprint);
61
+ SSE_FUNC_PROCESS(ispunct, ispunct);
62
+ SSE_FUNC_PROCESS(isspace, isspace);
63
+ SSE_FUNC_PROCESS(isupper, isupper);
64
+ SSE_FUNC_PROCESS(isxdigit, isxdigit);
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);
69
+ SSE_FUNC_PROCESS(sinh, sinh);
70
+ SSE_FUNC_PROCESS(cosh, cosh);
71
+ SSE_FUNC_PROCESS(tanh, tanh);
72
+
73
+ auto sse_svf_assert = [this](const CallICFGNode* callNode)
74
+ {
75
+ AbstractInterpretation::getAEInstance().checkpoints.erase(callNode);
76
+ u32_t arg0 = svfir->getValueNode(callNode->getArgument(0));
77
+ AbstractState&as = getAbsStateFromTrace(callNode);
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 = svfir->getValueNode(callNode->getArgument(0));
94
+ u32_t arg1 = svfir->getValueNode(callNode->getArgument(1));
95
+ AbstractState&as = getAbsStateFromTrace(callNode);
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;
112
+ AbstractState&as = getAbsStateFromTrace(callNode);
113
+ u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
114
+ std::string text = strRead(as, getSVFVar(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;
126
+ AbstractState&as = getAbsStateFromTrace(callNode);
127
+ AbstractValue& num = as[svfir->getValueNode(callNode->getArgument(0))];
128
+ AbstractValue& lb = as[svfir->getValueNode(callNode->getArgument(1))];
129
+ AbstractValue& ub = as[svfir->getValueNode(callNode->getArgument(2))];
130
+ assert(lb.getInterval().is_numeral() && ub.getInterval().is_numeral());
131
+ num.getInterval().set_to_top();
132
+ num.getInterval().meet_with(IntervalValue(lb.getInterval().lb(), ub.getInterval().ub()));
133
+ if (icfg->hasICFGNode(SVFUtil::cast<SVFInstruction>(callNode->getArgument(0))))
134
+ {
135
+ const ICFGNode* node = icfg->getICFGNode(SVFUtil::cast<SVFInstruction>(callNode->getArgument(0)));
136
+ for (const SVFStmt* stmt: node->getSVFStmts())
137
+ {
138
+ if (SVFUtil::isa<LoadStmt>(stmt))
139
+ {
140
+ const LoadStmt* load = SVFUtil::cast<LoadStmt>(stmt);
141
+ NodeID rhsId = load->getRHSVarID();
142
+ as.storeValue(rhsId, num);
143
+ }
144
+ }
145
+ }
146
+ return;
147
+ };
148
+ func_map["set_value"] = svf_set_value;
149
+
150
+ auto sse_scanf = [&](const CallICFGNode* callNode)
151
+ {
152
+ AbstractState& as = getAbsStateFromTrace(callNode);
153
+ //scanf("%d", &data);
154
+ if (callNode->arg_size() < 2) return;
155
+
156
+ u32_t dst_id = svfir->getValueNode(callNode->getArgument(1));
157
+ if (!as.inVarToAddrsTable(dst_id))
158
+ {
159
+ return;
160
+ }
161
+ else
162
+ {
163
+ AbstractValue Addrs = as[dst_id];
164
+ for (auto vaddr: Addrs.getAddrs())
165
+ {
166
+ u32_t objId = AbstractState::getInternalID(vaddr);
167
+ AbstractValue range = getRangeLimitFromType(svfir->getGNode(objId)->getType());
168
+ as.store(vaddr, range);
169
+ }
170
+ }
171
+ };
172
+ auto sse_fscanf = [&](const CallICFGNode* callNode)
173
+ {
174
+ //fscanf(stdin, "%d", &data);
175
+ if (callNode->arg_size() < 3) return;
176
+ AbstractState& as = getAbsStateFromTrace(callNode);
177
+ u32_t dst_id = svfir->getValueNode(callNode->getArgument(2));
178
+ if (!as.inVarToAddrsTable(dst_id))
179
+ {
180
+ }
181
+ else
182
+ {
183
+ AbstractValue Addrs = as[dst_id];
184
+ for (auto vaddr: Addrs.getAddrs())
185
+ {
186
+ u32_t objId = AbstractState::getInternalID(vaddr);
187
+ AbstractValue range = getRangeLimitFromType(svfir->getGNode(objId)->getType());
188
+ as.store(vaddr, range);
189
+ }
190
+ }
191
+ };
192
+
193
+ func_map["__isoc99_fscanf"] = sse_fscanf;
194
+ func_map["__isoc99_scanf"] = sse_scanf;
195
+ func_map["__isoc99_vscanf"] = sse_scanf;
196
+ func_map["fscanf"] = sse_fscanf;
197
+ func_map["scanf"] = sse_scanf;
198
+ func_map["sscanf"] = sse_scanf;
199
+ func_map["__isoc99_sscanf"] = sse_scanf;
200
+ func_map["vscanf"] = sse_scanf;
201
+
202
+ auto sse_fread = [&](const CallICFGNode *callNode)
203
+ {
204
+ if (callNode->arg_size() < 3) return;
205
+ AbstractState&as = getAbsStateFromTrace(callNode);
206
+ u32_t block_count_id = svfir->getValueNode(callNode->getArgument(2));
207
+ u32_t block_size_id = svfir->getValueNode(callNode->getArgument(1));
208
+ IntervalValue block_count = as[block_count_id].getInterval();
209
+ IntervalValue block_size = as[block_size_id].getInterval();
210
+ IntervalValue block_byte = block_count * block_size;
211
+ };
212
+ func_map["fread"] = sse_fread;
213
+
214
+ auto sse_sprintf = [&](const CallICFGNode *callNode)
215
+ {
216
+ // printf is difficult to predict since it has no byte size arguments
217
+ };
218
+
219
+ auto sse_snprintf = [&](const CallICFGNode *callNode)
220
+ {
221
+ if (callNode->arg_size() < 2) return;
222
+ AbstractState&as = getAbsStateFromTrace(callNode);
223
+ u32_t size_id = svfir->getValueNode(callNode->getArgument(1));
224
+ u32_t dst_id = svfir->getValueNode(callNode->getArgument(0));
225
+ // get elem size of arg2
226
+ u32_t elemSize = 1;
227
+ if (callNode->getArgument(2)->getType()->isArrayTy())
228
+ {
229
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(callNode->getArgument(2)->getType())->getTypeOfElement()->getByteSize();
230
+ }
231
+ else if (callNode->getArgument(2)->getType()->isPointerTy())
232
+ {
233
+ elemSize = as.getPointeeElement(svfir->getValueNode(callNode->getArgument(2)))->getByteSize();
234
+ }
235
+ else
236
+ {
237
+ return;
238
+ // assert(false && "we cannot support this type");
239
+ }
240
+ IntervalValue size = as[size_id].getInterval() * IntervalValue(elemSize) - IntervalValue(1);
241
+ if (!as.inVarToAddrsTable(dst_id))
242
+ {
243
+ }
244
+ };
245
+ func_map["__snprintf_chk"] = sse_snprintf;
246
+ func_map["__vsprintf_chk"] = sse_sprintf;
247
+ func_map["__sprintf_chk"] = sse_sprintf;
248
+ func_map["snprintf"] = sse_snprintf;
249
+ func_map["sprintf"] = sse_sprintf;
250
+ func_map["vsprintf"] = sse_sprintf;
251
+ func_map["vsnprintf"] = sse_snprintf;
252
+ func_map["__vsnprintf_chk"] = sse_snprintf;
253
+ func_map["swprintf"] = sse_snprintf;
254
+ func_map["_snwprintf"] = sse_snprintf;
255
+
256
+
257
+ auto sse_itoa = [&](const CallICFGNode* callNode)
258
+ {
259
+ // itoa(num, ch, 10);
260
+ // num: int, ch: char*, 10 is decimal
261
+ if (callNode->arg_size() < 3) return;
262
+ AbstractState&as = getAbsStateFromTrace(callNode);
263
+ u32_t num_id = svfir->getValueNode(callNode->getArgument(0));
264
+
265
+ u32_t num = (u32_t) as[num_id].getInterval().getNumeral();
266
+ std::string snum = std::to_string(num);
267
+ };
268
+ func_map["itoa"] = sse_itoa;
269
+
270
+
271
+ auto sse_strlen = [&](const CallICFGNode *callNode)
272
+ {
273
+ // check the arg size
274
+ if (callNode->arg_size() < 1) return;
275
+ const SVFValue* strValue = callNode->getArgument(0);
276
+ AbstractState& as = getAbsStateFromTrace(callNode);
277
+ NodeID value_id = svfir->getValueNode(strValue);
278
+ u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
279
+ u32_t dst_size = 0;
280
+ for (const auto& addr : as[value_id].getAddrs())
281
+ {
282
+ NodeID objId = AbstractState::getInternalID(addr);
283
+ if (svfir->getBaseObj(objId)->isConstantByteSize())
284
+ {
285
+ dst_size = svfir->getBaseObj(objId)->getByteSizeOfObj();
286
+ }
287
+ else
288
+ {
289
+ const ICFGNode* addrNode = svfir->getICFG()->getICFGNode(SVFUtil::cast<SVFInstruction>(svfir->getBaseObj(objId)->getValue()));
290
+ for (const SVFStmt* stmt2: addrNode->getSVFStmts())
291
+ {
292
+ if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
293
+ {
294
+ dst_size = as.getAllocaInstByteSize(addrStmt);
295
+ }
296
+ }
297
+ }
298
+ }
299
+ u32_t len = 0;
300
+ NodeID dstid = svfir->getValueNode(strValue);
301
+ if (as.inVarToAddrsTable(dstid))
302
+ {
303
+ for (u32_t index = 0; index < dst_size; index++)
304
+ {
305
+ AbstractValue expr0 =
306
+ as.getGepObjAddrs(dstid, IntervalValue(index));
307
+ AbstractValue val;
308
+ for (const auto &addr: expr0.getAddrs())
309
+ {
310
+ val.join_with(as.load(addr));
311
+ }
312
+ if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
313
+ {
314
+ break;
315
+ }
316
+ ++len;
317
+ }
318
+ }
319
+ if (len == 0)
320
+ {
321
+ as[lhsId] = IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit());
322
+ }
323
+ else
324
+ {
325
+ as[lhsId] = IntervalValue(len);
326
+ }
327
+ };
328
+ func_map["strlen"] = sse_strlen;
329
+ func_map["wcslen"] = sse_strlen;
330
+
331
+ auto sse_recv = [&](const CallICFGNode *callNode)
332
+ {
333
+ // recv(sockfd, buf, len, flags);
334
+ if (callNode->arg_size() < 4) return;
335
+ AbstractState&as = getAbsStateFromTrace(callNode);
336
+ u32_t len_id = svfir->getValueNode(callNode->getArgument(2));
337
+ IntervalValue len = as[len_id].getInterval() - IntervalValue(1);
338
+ u32_t lhsId = svfir->getValueNode(callNode->getCallSite());
339
+ as[lhsId] = len;
340
+ };
341
+ func_map["recv"] = sse_recv;
342
+ func_map["__recv"] = sse_recv;
343
+ };
344
+
345
+ AbstractState& AbsExtAPI::getAbsStateFromTrace(const SVF::ICFGNode* node)
346
+ {
347
+ const ICFGNode* repNode = icfg->getRepNode(node);
348
+ if (abstractTrace.count(repNode) == 0)
349
+ {
350
+ assert(0 && "No preAbsTrace for this node");
351
+ }
352
+ else
353
+ {
354
+ return abstractTrace[repNode];
355
+ }
356
+ }
357
+
358
+ std::string AbsExtAPI::strRead(AbstractState& as, const SVFVar* rhs)
359
+ {
360
+ // sse read string nodeID->string
361
+ std::string str0;
362
+
363
+ for (u32_t index = 0; index < Options::MaxFieldLimit(); index++)
364
+ {
365
+ // dead loop for string and break if there's a \0. If no \0, it will throw err.
366
+ if (!as.inVarToAddrsTable(rhs->getId())) continue;
367
+ AbstractValue expr0 =
368
+ as.getGepObjAddrs(rhs->getId(), IntervalValue(index));
369
+
370
+ AbstractValue val;
371
+ for (const auto &addr: expr0.getAddrs())
372
+ {
373
+ val.join_with(as.load(addr));
374
+ }
375
+ if (!val.getInterval().is_numeral())
376
+ {
377
+ break;
378
+ }
379
+ if ((char) val.getInterval().getIntNumeral() == '\0')
380
+ {
381
+ break;
382
+ }
383
+ str0.push_back((char) val.getInterval().getIntNumeral());
384
+ }
385
+ return str0;
386
+ }
387
+
388
+ void AbsExtAPI::handleExtAPI(const CallICFGNode *call)
389
+ {
390
+ AbstractState& as = getAbsStateFromTrace(call);
391
+ const SVFFunction *fun = call->getCalledFunction();
392
+ assert(fun && "SVFFunction* is nullptr");
393
+ ExtAPIType extType = UNCLASSIFIED;
394
+ // get type of mem api
395
+ for (const std::string &annotation: ExtAPI::getExtAPI()->getExtFuncAnnotations(fun))
396
+ {
397
+ if (annotation.find("MEMCPY") != std::string::npos)
398
+ extType = MEMCPY;
399
+ if (annotation.find("MEMSET") != std::string::npos)
400
+ extType = MEMSET;
401
+ if (annotation.find("STRCPY") != std::string::npos)
402
+ extType = STRCPY;
403
+ if (annotation.find("STRCAT") != std::string::npos)
404
+ extType = STRCAT;
405
+ }
406
+ if (extType == UNCLASSIFIED)
407
+ {
408
+ if (func_map.find(fun->getName()) != func_map.end())
409
+ {
410
+ func_map[fun->getName()](call);
411
+ }
412
+ else
413
+ {
414
+ u32_t lhsId = svfir->getValueNode(call->getCallSite());
415
+ if (as.inVarToAddrsTable(lhsId))
416
+ {
417
+
418
+ }
419
+ else
420
+ {
421
+ as[lhsId] = IntervalValue();
422
+ }
423
+ return;
424
+ }
425
+ }
426
+ // 1. memcpy functions like memcpy_chk, strncpy, annotate("MEMCPY"), annotate("BUF_CHECK:Arg0, Arg2"), annotate("BUF_CHECK:Arg1, Arg2")
427
+ else if (extType == MEMCPY)
428
+ {
429
+ IntervalValue len = as[svfir->getValueNode(call->getArgument(2))].getInterval();
430
+ svfir->getGNode(svfir->getValueNode(call->getArgument(0)));
431
+ handleMemcpy(as, getSVFVar(call->getArgument(0)), getSVFVar(call->getArgument(1)), len, 0);
432
+ }
433
+ else if (extType == MEMSET)
434
+ {
435
+ // memset dst is arg0, elem is arg1, size is arg2
436
+ IntervalValue len = as[svfir->getValueNode(call->getArgument(2))].getInterval();
437
+ IntervalValue elem = as[svfir->getValueNode(call->getArgument(1))].getInterval();
438
+ handleMemset(as, getSVFVar(call->getArgument(0)), elem, len);
439
+ }
440
+ else if (extType == STRCPY)
441
+ {
442
+ handleStrcpy(call);
443
+ }
444
+ else if (extType == STRCAT)
445
+ {
446
+ handleStrcat(call);
447
+ }
448
+ else
449
+ {
450
+
451
+ }
452
+ return;
453
+ }
454
+
455
+ void AbsExtAPI::handleStrcpy(const CallICFGNode *call)
456
+ {
457
+ // strcpy, __strcpy_chk, stpcpy , wcscpy, __wcscpy_chk
458
+ // get the dst and src
459
+ AbstractState& as = getAbsStateFromTrace(call);
460
+ const SVFVar* arg0Val = getSVFVar(call->getArgument(0));
461
+ const SVFVar* arg1Val = getSVFVar(call->getArgument(1));
462
+ IntervalValue strLen = getStrlen(as, arg1Val);
463
+ // no need to -1, since it has \0 as the last byte
464
+ handleMemcpy(as, arg0Val, arg1Val, strLen, strLen.lb().getIntNumeral());
465
+ }
466
+
467
+ IntervalValue AbsExtAPI::getStrlen(AbstractState& as, const SVF::SVFVar *strValue)
468
+ {
469
+ NodeID value_id = strValue->getId();
470
+ u32_t dst_size = 0;
471
+ for (const auto& addr : as[value_id].getAddrs())
472
+ {
473
+ NodeID objId = AbstractState::getInternalID(addr);
474
+ if (svfir->getBaseObj(objId)->isConstantByteSize())
475
+ {
476
+ dst_size = svfir->getBaseObj(objId)->getByteSizeOfObj();
477
+ }
478
+ else
479
+ {
480
+ const ICFGNode* addrNode = svfir->getICFG()->getICFGNode(SVFUtil::cast<SVFInstruction>(svfir->getBaseObj(objId)->getValue()));
481
+ for (const SVFStmt* stmt2: addrNode->getSVFStmts())
482
+ {
483
+ if (const AddrStmt* addrStmt = SVFUtil::dyn_cast<AddrStmt>(stmt2))
484
+ {
485
+ dst_size = as.getAllocaInstByteSize(addrStmt);
486
+ }
487
+ }
488
+ }
489
+ }
490
+ u32_t len = 0;
491
+ u32_t elemSize = 1;
492
+ if (as.inVarToAddrsTable(value_id))
493
+ {
494
+ for (u32_t index = 0; index < dst_size; index++)
495
+ {
496
+ AbstractValue expr0 =
497
+ as.getGepObjAddrs(value_id, IntervalValue(index));
498
+ AbstractValue val;
499
+ for (const auto &addr: expr0.getAddrs())
500
+ {
501
+ val.join_with(as.load(addr));
502
+ }
503
+ if (val.getInterval().is_numeral() && (char) val.getInterval().getIntNumeral() == '\0')
504
+ {
505
+ break;
506
+ }
507
+ ++len;
508
+ }
509
+ if (strValue->getType()->isArrayTy())
510
+ {
511
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(strValue->getType())->getTypeOfElement()->getByteSize();
512
+ }
513
+ else if (strValue->getType()->isPointerTy())
514
+ {
515
+ if (const SVFType* elemType = as.getPointeeElement(value_id))
516
+ {
517
+ if (elemType->isArrayTy())
518
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
519
+ else
520
+ elemSize = elemType->getByteSize();
521
+ }
522
+ else
523
+ {
524
+ elemSize = 1;
525
+ }
526
+ }
527
+ else
528
+ {
529
+ assert(false && "we cannot support this type");
530
+ }
531
+ }
532
+ if (len == 0)
533
+ {
534
+ return IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit());
535
+ }
536
+ else
537
+ {
538
+ return IntervalValue(len * elemSize);
539
+ }
540
+ }
541
+
542
+
543
+ void AbsExtAPI::handleStrcat(const SVF::CallICFGNode *call)
544
+ {
545
+ // __strcat_chk, strcat, __wcscat_chk, wcscat, __strncat_chk, strncat, __wcsncat_chk, wcsncat
546
+ // to check it is strcat group or strncat group
547
+ AbstractState& as = getAbsStateFromTrace(call);
548
+ const SVFFunction *fun = call->getCalledFunction();
549
+ const std::vector<std::string> strcatGroup = {"__strcat_chk", "strcat", "__wcscat_chk", "wcscat"};
550
+ const std::vector<std::string> strncatGroup = {"__strncat_chk", "strncat", "__wcsncat_chk", "wcsncat"};
551
+ if (std::find(strcatGroup.begin(), strcatGroup.end(), fun->getName()) != strcatGroup.end())
552
+ {
553
+ const SVFVar* arg0Val = getSVFVar(call->getArgument(0));
554
+ const SVFVar* arg1Val = getSVFVar(call->getArgument(1));
555
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
556
+ IntervalValue strLen1 = getStrlen(as, arg1Val);
557
+ IntervalValue totalLen = strLen0 + strLen1;
558
+ handleMemcpy(as, arg0Val, arg1Val, strLen1, strLen0.lb().getIntNumeral());
559
+ // do memcpy
560
+ }
561
+ else if (std::find(strncatGroup.begin(), strncatGroup.end(), fun->getName()) != strncatGroup.end())
562
+ {
563
+ const SVFVar* arg0Val = getSVFVar(call->getArgument(0));
564
+ const SVFVar* arg1Val = getSVFVar(call->getArgument(1));
565
+ const SVFVar* arg2Val = getSVFVar(call->getArgument(2));
566
+ IntervalValue arg2Num = as[arg2Val->getId()].getInterval();
567
+ IntervalValue strLen0 = getStrlen(as, arg0Val);
568
+ IntervalValue totalLen = strLen0 + arg2Num;
569
+ handleMemcpy(as, arg0Val, arg1Val, arg2Num, strLen0.lb().getIntNumeral());
570
+ // do memcpy
571
+ }
572
+ else
573
+ {
574
+ assert(false && "unknown strcat function, please add it to strcatGroup or strncatGroup");
575
+ }
576
+ }
577
+
578
+ void AbsExtAPI::handleMemcpy(AbstractState& as, const SVF::SVFVar *dst, const SVF::SVFVar *src, IntervalValue len, u32_t start_idx)
579
+ {
580
+ u32_t dstId = dst->getId(); // pts(dstId) = {objid} objbar objtypeinfo->getType().
581
+ u32_t srcId = src->getId();
582
+ u32_t elemSize = 1;
583
+ if (dst->getType()->isArrayTy())
584
+ {
585
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
586
+ }
587
+ // memcpy(i32*, i32*, 40)
588
+ else if (dst->getType()->isPointerTy())
589
+ {
590
+ if (const SVFType* elemType = as.getPointeeElement(dstId))
591
+ {
592
+ if (elemType->isArrayTy())
593
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(elemType)->getTypeOfElement()->getByteSize();
594
+ else
595
+ elemSize = elemType->getByteSize();
596
+ }
597
+ else
598
+ {
599
+ elemSize = 1;
600
+ }
601
+ }
602
+ else
603
+ {
604
+ assert(false && "we cannot support this type");
605
+ }
606
+ u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
607
+ u32_t range_val = size / elemSize;
608
+ if (as.inVarToAddrsTable(srcId) && as.inVarToAddrsTable(dstId))
609
+ {
610
+ for (u32_t index = 0; index < range_val; index++)
611
+ {
612
+ // dead loop for string and break if there's a \0. If no \0, it will throw err.
613
+ AbstractValue expr_src =
614
+ as.getGepObjAddrs(srcId, IntervalValue(index));
615
+ AbstractValue expr_dst =
616
+ as.getGepObjAddrs(dstId, IntervalValue(index + start_idx));
617
+ for (const auto &dst: expr_dst.getAddrs())
618
+ {
619
+ for (const auto &src: expr_src.getAddrs())
620
+ {
621
+ u32_t objId = AbstractState::getInternalID(src);
622
+ if (as.inAddrToValTable(objId))
623
+ {
624
+ as.store(dst, as.load(src));
625
+ }
626
+ else if (as.inAddrToAddrsTable(objId))
627
+ {
628
+ as.store(dst, as.load(src));
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ }
635
+
636
+ void AbsExtAPI::handleMemset(AbstractState& as, const SVF::SVFVar *dst, IntervalValue elem, IntervalValue len)
637
+ {
638
+ u32_t dstId = dst->getId();
639
+ u32_t size = std::min((u32_t)Options::MaxFieldLimit(), (u32_t) len.lb().getIntNumeral());
640
+ u32_t elemSize = 1;
641
+ if (dst->getType()->isArrayTy())
642
+ {
643
+ elemSize = SVFUtil::dyn_cast<SVFArrayType>(dst->getType())->getTypeOfElement()->getByteSize();
644
+ }
645
+ else if (dst->getType()->isPointerTy())
646
+ {
647
+ if (const SVFType* elemType = as.getPointeeElement(dstId))
648
+ {
649
+ elemSize = elemType->getByteSize();
650
+ }
651
+ else
652
+ {
653
+ elemSize = 1;
654
+ }
655
+ }
656
+ else
657
+ {
658
+ assert(false && "we cannot support this type");
659
+ }
660
+
661
+ u32_t range_val = size / elemSize;
662
+ for (u32_t index = 0; index < range_val; index++)
663
+ {
664
+ // dead loop for string and break if there's a \0. If no \0, it will throw err.
665
+ if (as.inVarToAddrsTable(dstId))
666
+ {
667
+ AbstractValue lhs_gep = as.getGepObjAddrs(dstId, IntervalValue(index));
668
+ for (const auto &addr: lhs_gep.getAddrs())
669
+ {
670
+ u32_t objId = AbstractState::getInternalID(addr);
671
+ if (as.inAddrToValTable(objId))
672
+ {
673
+ AbstractValue tmp = as.load(addr);
674
+ tmp.join_with(elem);
675
+ as.store(addr, tmp);
676
+ }
677
+ else
678
+ {
679
+ as.store(addr, elem);
680
+ }
681
+ }
682
+ }
683
+ else
684
+ break;
685
+ }
686
+ }
687
+
688
+ /**
689
+ * This function, getRangeLimitFromType, calculates the lower and upper bounds of
690
+ * a numeric range for a given SVFType. It is used to determine the possible value
691
+ * range of integer types. If the type is an SVFIntegerType, it calculates the bounds
692
+ * based on the size and signedness of the type. The calculated bounds are returned
693
+ * as an IntervalValue representing the lower (lb) and upper (ub) limits of the range.
694
+ *
695
+ * @param type The SVFType for which to calculate the value range.
696
+ *
697
+ * @return An IntervalValue representing the lower and upper bounds of the range.
698
+ */
699
+ IntervalValue AbsExtAPI::getRangeLimitFromType(const SVFType* type)
700
+ {
701
+ if (const SVFIntegerType* intType = SVFUtil::dyn_cast<SVFIntegerType>(type))
702
+ {
703
+ u32_t bits = type->getByteSize() * 8;
704
+ s64_t ub = 0;
705
+ s64_t lb = 0;
706
+ if (bits >= 32)
707
+ {
708
+ if (intType->isSigned())
709
+ {
710
+ ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
711
+ lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
712
+ }
713
+ else
714
+ {
715
+ ub = static_cast<s64_t>(std::numeric_limits<u32_t>::max());
716
+ lb = static_cast<s64_t>(std::numeric_limits<u32_t>::min());
717
+ }
718
+ }
719
+ else if (bits == 16)
720
+ {
721
+ if (intType->isSigned())
722
+ {
723
+ ub = static_cast<s64_t>(std::numeric_limits<s16_t>::max());
724
+ lb = static_cast<s64_t>(std::numeric_limits<s16_t>::min());
725
+ }
726
+ else
727
+ {
728
+ ub = static_cast<s64_t>(std::numeric_limits<u16_t>::max());
729
+ lb = static_cast<s64_t>(std::numeric_limits<u16_t>::min());
730
+ }
731
+ }
732
+ else if (bits == 8)
733
+ {
734
+ if (intType->isSigned())
735
+ {
736
+ ub = static_cast<s64_t>(std::numeric_limits<int8_t>::max());
737
+ lb = static_cast<s64_t>(std::numeric_limits<int8_t>::min());
738
+ }
739
+ else
740
+ {
741
+ ub = static_cast<s64_t>(std::numeric_limits<u_int8_t>::max());
742
+ lb = static_cast<s64_t>(std::numeric_limits<u_int8_t>::min());
743
+ }
744
+ }
745
+ return IntervalValue(lb, ub);
746
+ }
747
+ else if (SVFUtil::isa<SVFOtherType>(type))
748
+ {
749
+ // handle other type like float double, set s32_t as the range
750
+ s64_t ub = static_cast<s64_t>(std::numeric_limits<s32_t>::max());
751
+ s64_t lb = static_cast<s64_t>(std::numeric_limits<s32_t>::min());
752
+ return IntervalValue(lb, ub);
753
+ }
754
+ else
755
+ {
756
+ return IntervalValue::top();
757
+ // other types, return top interval
758
+ }
759
+ }
760
+
761
+ const SVFVar* AbsExtAPI::getSVFVar(const SVF::SVFValue* val)
762
+ {
763
+ assert(svfir->hasGNode(svfir->getValueNode(val)));
764
+ return svfir->getGNode(svfir->getValueNode(val));
765
+ }