Skip to content

Commit e014bee

Browse files
authored
Add one more test for Assign-3 and add handleMemcpy in Python
update ass3
2 parents 7746314 + 457af35 commit e014bee

File tree

3 files changed

+156
-99
lines changed

3 files changed

+156
-99
lines changed

Assignment-3/Python/Assignment_3_Helper.py

Lines changed: 27 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -261,107 +261,36 @@ def updateGepObjOffsetFromBase(self, abstractState: pysvf.AbstractState, gepAddr
261261
raise AssertionError("gepRhsObjVar has no gepObjOffsetFromBase")
262262

263263

264-
def getStrlen(self, abstractState, strValue):
264+
def handleMemcpy(self, abstractState: pysvf.AbstractState, dst: pysvf.SVFVar, src: pysvf.SVFVar, len: pysvf.IntervalValue, start_idx: int):
265265
"""
266-
Calculate the length of a string in the abstract state.
267-
268-
:param abstractState: The abstract state containing variable information.
269-
:param strValue: The SVF variable representing the string.
270-
:return: An IntervalValue representing the string length.
266+
Handle a memcpy operation in the abstract state.
271267
"""
272-
value_id = strValue.getId()
273-
dst_size = 0
274-
max_limit = 10000 # Prevent infinite or corrupted symbolic memory
275-
276-
# Determine the size of the destination object
277-
for addr in abstractState[value_id].getAddrs():
278-
obj_id = abstractState.getIDFromAddr(addr)
279-
280-
try:
281-
base_object = self.svfir.getBaseObject(obj_id)
282-
except Exception as e:
283-
print(f"[warn] failed to get base object for obj_id {obj_id}: {e}")
284-
continue
285-
286-
if not base_object:
287-
continue
288-
289-
if base_object.isConstantByteSize():
290-
dst_size = base_object.getByteSizeOfObj()
291-
else:
292-
icfg_node = base_object.getICFGNode()
293-
for stmt in icfg_node.getSVFStmts():
294-
if isinstance(stmt, pysvf.AddrStmt):
295-
try:
296-
dst_size = abstractState.getAllocaInstByteSize(stmt)
297-
break
298-
except Exception as e:
299-
print(f"[warn] failed to get alloca size: {e}")
300-
continue
301-
302-
# If we've determined a reasonable size, stop
303-
if dst_size > 0:
304-
break
305-
306-
# Safety cap
307-
if dst_size == 0 or dst_size > max_limit:
308-
dst_size = max_limit
309-
310-
length = 0
311-
elem_size = 1
312-
313-
# Calculate string length
314-
if abstractState.isAddr(value_id):
315-
for index in range(dst_size):
316-
try:
317-
expr0 = abstractState.getGepObjAddrs(value_id, pysvf.IntervalValue(index))
318-
except Exception as e:
319-
print(f"[warn] getGepObjAddrs failed at index {index}: {e}")
320-
break
321-
322-
val = pysvf.AbstractValue()
323-
324-
for addr in expr0:
325-
try:
326-
val.join_with(abstractState.load(addr))
327-
except Exception as e:
328-
print(f"[warn] load from addr {addr} failed: {e}")
329-
continue
330-
331-
iv = val.getInterval()
332-
if iv.isInterval():
333-
try:
334-
if chr(iv.getIntNumeral()) == '\0':
335-
break
336-
except:
337-
break
338-
length += 1
339-
340-
# Determine element size
341-
try:
342-
ty = strValue.getType()
343-
if ty.isArrayTy():
344-
elem_size = ty.getTypeOfElement().getByteSize()
345-
elif ty.isPointerTy():
346-
elem_type = abstractState.getPointeeElement(value_id)
347-
if elem_type:
348-
if elem_type.isArrayTy():
349-
elem_size = elem_type.getTypeOfElement().getByteSize()
350-
else:
351-
elem_size = elem_type.getByteSize()
352-
else:
353-
elem_size = 1
268+
dstId = dst.getId()
269+
srcId = src.getId()
270+
elemSize = 1
271+
if isinstance(dst, pysvf.ValVar):
272+
if dst.getType().isArrayTy():
273+
elemSize = dst.getType().getTypeOfElement().getByteSize()
274+
elif dst.getType().isPointerTy():
275+
elemType = abstractState.getPointeeElement(dstId)
276+
if elemType.isArrayTy():
277+
elemSize = elemType.getTypeOfElement().getByteSize()
354278
else:
355-
raise AssertionError("Unsupported type")
356-
except Exception as e:
357-
print(f"[warn] failed to get element size: {e}")
358-
elem_size = 1
359-
360-
# Return as IntervalValue
361-
if length == 0:
362-
return pysvf.IntervalValue(0, pysvf.Options.max_field_limit())
363-
else:
364-
return pysvf.IntervalValue(length * elem_size)
279+
elemSize = elemType.getByteSize()
280+
else:
281+
raise AssertionError("Unsupported type")
282+
size = len.lb().getNumeral()
283+
range_val = size/elemSize
284+
if abstractState.inVarToAddrsTable(dstId) and abstractState.inVarToAddrsTable(srcId):
285+
for index in range(0, int(range_val)):
286+
expr_src = abstractState.getGepObjAddrs(srcId, pysvf.IntervalValue(index))
287+
expr_dst = abstractState.getGepObjAddrs(dstId, pysvf.IntervalValue(index + start_idx))
288+
for addr_src in expr_src:
289+
for addr_dst in expr_dst:
290+
objId = abstractState.getIDFromAddr(addr_src)
291+
if objId in abstractState.getLocToVal():
292+
lhs = abstractState.load(addr_src)
293+
abstractState.store(addr_dst, lhs)
365294

366295

367296
def getStrlen(self, abstractState, strValue):
@@ -1151,4 +1080,3 @@ def getAccessOffset(self, objId: int, gep: pysvf.GepStmt) -> pysvf.IntervalValue
11511080
else:
11521081
assert isinstance(obj, pysvf.DummyObjVar), "What other types of object?"
11531082
return pysvf.IntervalValue.top()
1154-

Assignment-3/Tests/buf/test6.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <stdbool.h>
2+
void mem_insert(void *buffer, const void *data, int data_size, int position);
3+
extern void OVERFLOW(void* data, int size);
4+
extern void svf_assert(bool condition);
5+
int main() {
6+
char buffer[10] = {0};
7+
mem_insert(buffer, "abcdef", 3, 5);
8+
svf_assert(buffer[3] == 'a');
9+
svf_assert(buffer[4] == 'b');
10+
svf_assert(buffer[5] == 'c');
11+
svf_assert(buffer[6] == 'd');
12+
svf_assert(buffer[7] == 'e');
13+
svf_assert(buffer[8] != 'f');
14+
return 0;
15+
}

Assignment-3/Tests/buf/test6.ll

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
; ModuleID = './test14.ll'
2+
source_filename = "test14.c"
3+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
4+
target triple = "arm64-apple-macosx14.0.0"
5+
6+
@.str = private unnamed_addr constant [7 x i8] c"abcdef\00", align 1, !dbg !0
7+
8+
; Function Attrs: noinline nounwind ssp uwtable(sync)
9+
define i32 @main() #0 !dbg !16 {
10+
entry:
11+
%buffer = alloca [10 x i8], align 1
12+
call void @llvm.dbg.declare(metadata ptr %buffer, metadata !21, metadata !DIExpression()), !dbg !25
13+
call void @llvm.memset.p0.i64(ptr align 1 %buffer, i8 0, i64 10, i1 false), !dbg !25
14+
%arraydecay = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 0, !dbg !26
15+
call void @mem_insert(ptr noundef %arraydecay, ptr noundef @.str, i32 noundef 3, i32 noundef 5), !dbg !27
16+
%arrayidx = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 3, !dbg !28
17+
%0 = load i8, ptr %arrayidx, align 1, !dbg !28
18+
%conv = sext i8 %0 to i32, !dbg !28
19+
%cmp = icmp eq i32 %conv, 97, !dbg !29
20+
call void @svf_assert(i1 noundef zeroext %cmp), !dbg !30
21+
%arrayidx2 = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 4, !dbg !31
22+
%1 = load i8, ptr %arrayidx2, align 1, !dbg !31
23+
%conv3 = sext i8 %1 to i32, !dbg !31
24+
%cmp4 = icmp eq i32 %conv3, 98, !dbg !32
25+
call void @svf_assert(i1 noundef zeroext %cmp4), !dbg !33
26+
%arrayidx6 = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 5, !dbg !34
27+
%2 = load i8, ptr %arrayidx6, align 1, !dbg !34
28+
%conv7 = sext i8 %2 to i32, !dbg !34
29+
%cmp8 = icmp eq i32 %conv7, 99, !dbg !35
30+
call void @svf_assert(i1 noundef zeroext %cmp8), !dbg !36
31+
%arrayidx10 = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 6, !dbg !37
32+
%3 = load i8, ptr %arrayidx10, align 1, !dbg !37
33+
%conv11 = sext i8 %3 to i32, !dbg !37
34+
%cmp12 = icmp eq i32 %conv11, 100, !dbg !38
35+
call void @svf_assert(i1 noundef zeroext %cmp12), !dbg !39
36+
%arrayidx14 = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 7, !dbg !40
37+
%4 = load i8, ptr %arrayidx14, align 1, !dbg !40
38+
%conv15 = sext i8 %4 to i32, !dbg !40
39+
%cmp16 = icmp eq i32 %conv15, 101, !dbg !41
40+
call void @svf_assert(i1 noundef zeroext %cmp16), !dbg !42
41+
%arrayidx18 = getelementptr inbounds [10 x i8], ptr %buffer, i64 0, i64 8, !dbg !43
42+
%5 = load i8, ptr %arrayidx18, align 1, !dbg !43
43+
%conv19 = sext i8 %5 to i32, !dbg !43
44+
%cmp20 = icmp ne i32 %conv19, 102, !dbg !44
45+
call void @svf_assert(i1 noundef zeroext %cmp20), !dbg !45
46+
ret i32 0, !dbg !46
47+
}
48+
49+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
50+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
51+
52+
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
53+
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2
54+
55+
declare void @mem_insert(ptr noundef, ptr noundef, i32 noundef, i32 noundef) #3
56+
57+
declare void @svf_assert(i1 noundef zeroext) #3
58+
59+
attributes #0 = { noinline nounwind ssp uwtable(sync) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" }
60+
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
61+
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: write) }
62+
attributes #3 = { "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+crypto,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" }
63+
64+
!llvm.dbg.cu = !{!7}
65+
!llvm.module.flags = !{!9, !10, !11, !12, !13, !14}
66+
!llvm.ident = !{!15}
67+
68+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
69+
!1 = distinct !DIGlobalVariable(scope: null, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true)
70+
!2 = !DIFile(filename: "test14.c", directory: "/Users/z5489735/2023/0718/Software-Security-Analysis/Assignment-3/Tests/buf")
71+
!3 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 56, elements: !5)
72+
!4 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
73+
!5 = !{!6}
74+
!6 = !DISubrange(count: 7)
75+
!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !2, producer: "Homebrew clang version 16.0.6", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !8, splitDebugInlining: false, nameTableKind: None, sysroot: "/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk", sdk: "MacOSX14.sdk")
76+
!8 = !{!0}
77+
!9 = !{i32 7, !"Dwarf Version", i32 4}
78+
!10 = !{i32 2, !"Debug Info Version", i32 3}
79+
!11 = !{i32 1, !"wchar_size", i32 4}
80+
!12 = !{i32 8, !"PIC Level", i32 2}
81+
!13 = !{i32 7, !"uwtable", i32 1}
82+
!14 = !{i32 7, !"frame-pointer", i32 1}
83+
!15 = !{!"Homebrew clang version 16.0.6"}
84+
!16 = distinct !DISubprogram(name: "main", scope: !2, file: !2, line: 5, type: !17, scopeLine: 5, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !20)
85+
!17 = !DISubroutineType(types: !18)
86+
!18 = !{!19}
87+
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
88+
!20 = !{}
89+
!21 = !DILocalVariable(name: "buffer", scope: !16, file: !2, line: 6, type: !22)
90+
!22 = !DICompositeType(tag: DW_TAG_array_type, baseType: !4, size: 80, elements: !23)
91+
!23 = !{!24}
92+
!24 = !DISubrange(count: 10)
93+
!25 = !DILocation(line: 6, column: 7, scope: !16)
94+
!26 = !DILocation(line: 7, column: 13, scope: !16)
95+
!27 = !DILocation(line: 7, column: 2, scope: !16)
96+
!28 = !DILocation(line: 8, column: 16, scope: !16)
97+
!29 = !DILocation(line: 8, column: 26, scope: !16)
98+
!30 = !DILocation(line: 8, column: 5, scope: !16)
99+
!31 = !DILocation(line: 9, column: 16, scope: !16)
100+
!32 = !DILocation(line: 9, column: 26, scope: !16)
101+
!33 = !DILocation(line: 9, column: 5, scope: !16)
102+
!34 = !DILocation(line: 10, column: 16, scope: !16)
103+
!35 = !DILocation(line: 10, column: 26, scope: !16)
104+
!36 = !DILocation(line: 10, column: 5, scope: !16)
105+
!37 = !DILocation(line: 11, column: 16, scope: !16)
106+
!38 = !DILocation(line: 11, column: 26, scope: !16)
107+
!39 = !DILocation(line: 11, column: 5, scope: !16)
108+
!40 = !DILocation(line: 12, column: 16, scope: !16)
109+
!41 = !DILocation(line: 12, column: 26, scope: !16)
110+
!42 = !DILocation(line: 12, column: 5, scope: !16)
111+
!43 = !DILocation(line: 13, column: 16, scope: !16)
112+
!44 = !DILocation(line: 13, column: 26, scope: !16)
113+
!45 = !DILocation(line: 13, column: 5, scope: !16)
114+
!46 = !DILocation(line: 14, column: 5, scope: !16)

0 commit comments

Comments
 (0)