CNUproject/코드 동일성 검사 도구
23_IR에 Klee 함수 호출 직접 추가
YUMMMM
2023. 10. 19. 20:10
IR에 KLEE 함수 호출 코드 직접 삽입하는 것이 제대로 작동하지 않는지 확인
1. if문이 있는 코드, if의 조건이 하나만 만족하도록 하여 그때의 테스트 케이스만 생성하는지 확인
#include <stdio.h>
int get_sign(int x) {
if (x == 0)
return 0;
else if (x < 0)
return -1;
else
return 1;
}
int main() {
int a;
get_sign(a);
return 0;
}
; ModuleID = 'testKlee.c'
source_filename = "testKlee.c"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"
@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @get_sign(i32 %0) #0 {
%2 = alloca i32, align 4
%3 = alloca i32, align 4
store i32 %0, i32* %3, align 4
%4 = load i32, i32* %3, align 4
%5 = icmp eq i32 %4, 0
br i1 %5, label %6, label %7
6: ; preds = %1
store i32 0, i32* %2, align 4
br label %12
7: ; preds = %1
%8 = load i32, i32* %3, align 4
%9 = icmp slt i32 %8, 0
br i1 %9, label %10, label %11
10: ; preds = %7
store i32 -1, i32* %2, align 4
br label %12
11: ; preds = %7
store i32 1, i32* %2, align 4
br label %12
12: ; preds = %11, %10, %6
%13 = load i32, i32* %2, align 4
ret i32 %13
}
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
%symbol = bitcast i32* %2 to i8*
call void @klee_make_symbolic(i8* %symbol, i64 4, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0))
%symbol.ass = load i32, i32* %2, align 4
%cmp = icmp sgt i32 %symbol.ass, 0
%conv = zext i1 %cmp to i32
%conv1 = sext i32 %conv to i64
call void @klee_assume(i64 %conv1)
%3 = load i32, i32* %2, align 4
%4 = call i32 @get_sign(i32 %3)
ret i32 0
}
declare dso_local void @klee_make_symbolic(i8*, i64, i8*)
declare dso_local void @klee_assume(i64)
attributes #0 = { noinline nounwind optnone ssp uwtable "disable-tail-calls"="false" "frame-pointer"="non-leaf" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a12" "target-features"="+aes,+crc,+crypto,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+v8.3a,+zcm,+zcz" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 0}
!2 = !{i32 1, !"sign-return-address", i32 0}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{!"Homebrew clang version 12.0.1"}
main에서 a를 klee_make_symbolic으로 전달하고, a가 0보다 크다는 조건을 klee_assume에 전달하는 IR 추가
KLEE 실행시


a가 양수일 때의 테스트 케이스만 생성하는 것으로 보아 klee 함수를 호출하는 IR을 삽입한 것이 잘 동작하는 것을 알 수 있음
2. 지금껏 해오던 코드에서 결과값이 같지 않다는 조건 대신 같다는 조건을 넣었을 때 Provably false 에러 없이 잘 작동하는지 확인
#include <stdio.h>
int addResult;
int mulResult;
int addNum(int num) {
num += num;
return num;
}
int mulNum(int num) {
num *= 2;
return num;
}
int main() {
int num;
addResult = addNum(num);
mulResult = mulNum(num);
return 0;
}
; ModuleID = 'test3.c'
source_filename = "test3.c"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"
@.str = private unnamed_addr constant [5 x i8] c"num1\00", align 1
@.str.1 = private unnamed_addr constant [5 x i8] c"num2\00", align 1
@addResult = dso_local global i32 0, align 4
@mulResult = dso_local global i32 0, align 4
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @addNum(i32 %0) #0 {
%num = alloca i32, align 4
store i32 %0, i32* %num, align 4
%num.addr = bitcast i32* %num to i8*
call void @klee_make_symbolic(i8* %num.addr, i64 4, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = load i32, i32* %2, align 4
%5 = add nsw i32 %4, %3
store i32 %5, i32* %2, align 4
%6 = load i32, i32* %2, align 4
ret i32 %6
}
declare dso_local void @klee_make_symbolic(i8*, i64, i8*)
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @mulNum(i32 %0) #0 {
%num = alloca i32, align 4
store i32 %0, i32* %num, align 4
%num.addr = bitcast i32* %num to i8*
call void @klee_make_symbolic(i8* %num.addr, i64 4, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = mul nsw i32 %3, 2
store i32 %4, i32* %2, align 4
%5 = load i32, i32* %2, align 4
ret i32 %5
}
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
%3 = load i32, i32* %2, align 4
%4 = call i32 @addNum(i32 %3)
store i32 %4, i32* @addResult, align 4
%5 = load i32, i32* %2, align 4
%6 = call i32 @mulNum(i32 %5)
store i32 %6, i32* @mulResult, align 4
%7 = load i32, i32* @addResult, align 4
%8 = load i32, i32* @mulResult, align 4
; klee_assume 함수 호출
%cmp = icmp eq i32 %7, %8
%conv = zext i1 %cmp to i32
%conv2 = sext i32 %conv to i64
call void @klee_assume(i64 %conv2)
ret i32 0
}
declare dso_local void @klee_assume(i64)
attributes #0 = { noinline nounwind optnone ssp uwtable "disable-tail-calls"="false" "frame-pointer"="non-leaf" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a12" "target-features"="+aes,+crc,+crypto,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+v8.3a,+zcm,+zcz" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 0}
!2 = !{i32 1, !"sign-return-address", i32 0}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{!"Homebrew clang version 12.0.1"}
main에서 add와 mul 함수의 결과값이 서로 같다는 조건을 klee_assume에 전달하는 IR 추가
KLEE 실행시


Provably false 없이 정상 작동하는 것을 알 수 있음
3. num을 글로벌 변수로 생성하고, main에서 한 번만 Symbolic 변수로 생성
#include <stdio.h>
int num;
int addNum(int num) {
num += num;
return num;
}
int mulNum(int num) {
num *= 2;
return num;
}
int main() {
int add = addNum(num);
int mul = mulNum(num);
return 0;
}
; ModuleID = 'test4.c'
source_filename = "test4.c"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx13.0.0"
@num = dso_local global i32 0, align 4
@.str = private unnamed_addr constant [4 x i8] c"num\00", align 1
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @addNum(i32 %0) #0 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = load i32, i32* %2, align 4
%5 = add nsw i32 %4, %3
store i32 %5, i32* %2, align 4
%6 = load i32, i32* %2, align 4
ret i32 %6
}
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @mulNum(i32 %0) #0 {
%2 = alloca i32, align 4
store i32 %0, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = mul nsw i32 %3, 2
store i32 %4, i32* %2, align 4
%5 = load i32, i32* %2, align 4
ret i32 %5
}
; Function Attrs: noinline nounwind optnone ssp uwtable
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%symbol = bitcast i32* @num to i8*
call void @klee_make_symbolic(i8* %symbol, i64 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0))
store i32 0, i32* %1, align 4
%4 = load i32, i32* @num, align 4
%5 = call i32 @addNum(i32 %4)
store i32 %5, i32* %2, align 4
%6 = load i32, i32* @num, align 4
%7 = call i32 @mulNum(i32 %6)
store i32 %7, i32* %3, align 4
%8 = load i32, i32* %2, align 4
%9 = load i32, i32* %3, align 4
%cmp = icmp ne i32 %8, %9
%conv = zext i1 %cmp to i32
%conv2 = sext i32 %conv to i64
call void @klee_assume(i64 %conv2)
ret i32 0
}
declare dso_local void @klee_make_symbolic(i8*, i64, i8*)
declare dso_local void @klee_assume(i64)
attributes #0 = { noinline nounwind optnone ssp uwtable "disable-tail-calls"="false" "frame-pointer"="non-leaf" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a12" "target-features"="+aes,+crc,+crypto,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+v8.3a,+zcm,+zcz" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"branch-target-enforcement", i32 0}
!2 = !{i32 1, !"sign-return-address", i32 0}
!3 = !{i32 1, !"sign-return-address-all", i32 0}
!4 = !{i32 1, !"sign-return-address-with-bkey", i32 0}
!5 = !{i32 7, !"PIC Level", i32 2}
!6 = !{!"Homebrew clang version 12.0.1"}
main에서 함수 호출 전에 글로벌 변수 num을 klee_make_symbolic으로 전달하는 IR 추가
각 함수의 결과값이 같지 않다는 조건을 klee_assume으로 전달하는 IR 추가
KLEE 실행시

Provably false 에러 발생
IR에 KLEE 함수를 호출하는 코드를 직접 삽입해도 문제가 없는 것으로 확인됨