Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFCI][BoundsChecking] Apply nosanitize on local-bounds instrumentation #122416

126 changes: 84 additions & 42 deletions clang/test/CodeGen/allow-ubsan-check.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -mllvm -ubsan-guard-checks | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -mllvm -ubsan-guard-checks -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=TR
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -mllvm -ubsan-guard-checks -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=REC
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,local-bounds -mllvm -ubsan-guard-checks | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,local-bounds -mllvm -ubsan-guard-checks -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,local-bounds | FileCheck %s --check-prefixes=TR
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -O1 -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,local-bounds -mllvm -ubsan-guard-checks -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,local-bounds | FileCheck %s --check-prefixes=REC


// CHECK-LABEL: define dso_local noundef i32 @div(
Expand All @@ -18,7 +18,7 @@
// CHECK: [[HANDLER_DIVREM_OVERFLOW]]:
// CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: tail call void @__ubsan_handle_divrem_overflow_abort(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR4:[0-9]+]], !nosanitize [[META2]]
// CHECK-NEXT: tail call void @__ubsan_handle_divrem_overflow_abort(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR7:[0-9]+]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: [[CONT]]:
// CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
Expand All @@ -36,7 +36,7 @@
// TR-NEXT: [[DOTNOT1:%.*]] = and i1 [[DOTNOT3]], [[TMP3]]
// TR-NEXT: br i1 [[DOTNOT1]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]]
// TR: [[TRAP]]:
// TR-NEXT: tail call void @llvm.ubsantrap(i8 3) #[[ATTR4:[0-9]+]], !nosanitize [[META2]]
// TR-NEXT: tail call void @llvm.ubsantrap(i8 3) #[[ATTR6:[0-9]+]], !nosanitize [[META2]]
// TR-NEXT: unreachable, !nosanitize [[META2]]
// TR: [[CONT]]:
// TR-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
Expand All @@ -56,7 +56,7 @@
// REC: [[HANDLER_DIVREM_OVERFLOW]]:
// REC-NEXT: [[TMP4:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
// REC-NEXT: [[TMP5:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
// REC-NEXT: tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR4:[0-9]+]], !nosanitize [[META2]]
// REC-NEXT: tail call void @__ubsan_handle_divrem_overflow(ptr nonnull @[[GLOB1:[0-9]+]], i64 [[TMP4]], i64 [[TMP5]]) #[[ATTR7:[0-9]+]], !nosanitize [[META2]]
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
// REC: [[CONT]]:
// REC-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]]
Expand All @@ -67,46 +67,22 @@ int div(int x, int y) {
}

// CHECK-LABEL: define dso_local i32 @null(
// CHECK-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-SAME: ptr nocapture noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 22), !nosanitize [[META2]]
// CHECK-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
// CHECK-NEXT: br i1 [[DOTNOT1]], label %[[HANDLER_TYPE_MISMATCH:.*]], label %[[CONT:.*]], !prof [[PROF3]], !nosanitize [[META2]]
// CHECK: [[HANDLER_TYPE_MISMATCH]]:
// CHECK-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 0) #[[ATTR4]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: [[CONT]]:
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA4:![0-9]+]]
// CHECK-NEXT: ret i32 [[TMP2]]
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA4:![0-9]+]]
// CHECK-NEXT: ret i32 [[TMP0]]
//
// TR-LABEL: define dso_local i32 @null(
// TR-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
// TR-SAME: ptr nocapture noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// TR-NEXT: [[ENTRY:.*:]]
// TR-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
// TR-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 22), !nosanitize [[META2]]
// TR-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
// TR-NEXT: br i1 [[DOTNOT1]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]]
// TR: [[TRAP]]:
// TR-NEXT: tail call void @llvm.ubsantrap(i8 22) #[[ATTR4]], !nosanitize [[META2]]
// TR-NEXT: unreachable, !nosanitize [[META2]]
// TR: [[CONT]]:
// TR-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA3:![0-9]+]]
// TR-NEXT: ret i32 [[TMP2]]
// TR-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA3:![0-9]+]]
// TR-NEXT: ret i32 [[TMP0]]
//
// REC-LABEL: define dso_local i32 @null(
// REC-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
// REC-SAME: ptr nocapture noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// REC-NEXT: [[ENTRY:.*:]]
// REC-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
// REC-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 22), !nosanitize [[META2]]
// REC-NEXT: [[DOTNOT1:%.*]] = and i1 [[TMP0]], [[TMP1]]
// REC-NEXT: br i1 [[DOTNOT1]], label %[[HANDLER_TYPE_MISMATCH:.*]], label %[[CONT:.*]], !prof [[PROF3]], !nosanitize [[META2]]
// REC: [[HANDLER_TYPE_MISMATCH]]:
// REC-NEXT: tail call void @__ubsan_handle_type_mismatch_v1(ptr nonnull @[[GLOB2:[0-9]+]], i64 0) #[[ATTR4]], !nosanitize [[META2]]
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
// REC: [[CONT]]:
// REC-NEXT: [[TMP2:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA4:![0-9]+]]
// REC-NEXT: ret i32 [[TMP2]]
// REC-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA4:![0-9]+]]
// REC-NEXT: ret i32 [[TMP0]]
//
int null(int* x) {
return *x;
Expand All @@ -123,7 +99,7 @@ int null(int* x) {
// CHECK: [[HANDLER_ADD_OVERFLOW]]:
// CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: tail call void @__ubsan_handle_add_overflow_abort(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize [[META2]]
// CHECK-NEXT: tail call void @__ubsan_handle_add_overflow_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: [[CONT]]:
// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
Expand All @@ -138,7 +114,7 @@ int null(int* x) {
// TR-NEXT: [[DOTDEMORGAN:%.*]] = and i1 [[TMP1]], [[TMP2]]
// TR-NEXT: br i1 [[DOTDEMORGAN]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]]
// TR: [[TRAP]]:
// TR-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]]
// TR-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR6]], !nosanitize [[META2]]
// TR-NEXT: unreachable, !nosanitize [[META2]]
// TR: [[CONT]]:
// TR-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
Expand All @@ -155,7 +131,7 @@ int null(int* x) {
// REC: [[HANDLER_ADD_OVERFLOW]]:
// REC-NEXT: [[TMP3:%.*]] = zext i32 [[X]] to i64, !nosanitize [[META2]]
// REC-NEXT: [[TMP4:%.*]] = zext i32 [[Y]] to i64, !nosanitize [[META2]]
// REC-NEXT: tail call void @__ubsan_handle_add_overflow(ptr nonnull @[[GLOB3:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize [[META2]]
// REC-NEXT: tail call void @__ubsan_handle_add_overflow(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP3]], i64 [[TMP4]]) #[[ATTR7]], !nosanitize [[META2]]
// REC-NEXT: br label %[[CONT]], !nosanitize [[META2]]
// REC: [[CONT]]:
// REC-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]]
Expand All @@ -164,24 +140,90 @@ int null(int* x) {
int overflow(int x, int y) {
return x + y;
}

void use(double*);

// CHECK-LABEL: define dso_local double @f1(
// CHECK-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
// CHECK-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
// CHECK-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR8:[0-9]+]]
// CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
// CHECK-NEXT: [[DOTNOT:%.*]] = icmp ugt i64 [[TMP0]], [[IDXPROM]]
// CHECK-NEXT: br i1 [[DOTNOT]], label %[[BB1:.*]], label %[[TRAP:.*]]
// CHECK: [[BB1]]:
// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
// CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA8:![0-9]+]]
// CHECK-NEXT: ret double [[TMP2]]
// CHECK: [[TRAP]]:
// CHECK-NEXT: call void @__ubsan_handle_local_out_of_bounds_abort() #[[ATTR7]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
//
// TR-LABEL: define dso_local double @f1(
// TR-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
// TR-NEXT: [[ENTRY:.*:]]
// TR-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
// TR-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
// TR-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR7:[0-9]+]]
// TR-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
// TR-NEXT: [[DOTNOT:%.*]] = icmp ugt i64 [[TMP0]], [[IDXPROM]]
// TR-NEXT: br i1 [[DOTNOT]], label %[[BB1:.*]], label %[[TRAP:.*]]
// TR: [[BB1]]:
// TR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
// TR-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA7:![0-9]+]]
// TR-NEXT: ret double [[TMP2]]
// TR: [[TRAP]]:
// TR-NEXT: call void @llvm.ubsantrap(i8 3) #[[ATTR6]], !nosanitize [[META2]]
// TR-NEXT: unreachable, !nosanitize [[META2]]
//
// REC-LABEL: define dso_local double @f1(
// REC-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) local_unnamed_addr #[[ATTR0]] {
// REC-NEXT: [[ENTRY:.*:]]
// REC-NEXT: [[TMP0:%.*]] = zext i32 [[B]] to i64
// REC-NEXT: [[VLA:%.*]] = alloca double, i64 [[TMP0]], align 16
// REC-NEXT: call void @use(ptr noundef nonnull [[VLA]]) #[[ATTR6:[0-9]+]]
// REC-NEXT: [[IDXPROM:%.*]] = sext i32 [[I]] to i64
// REC-NEXT: [[DOTNOT:%.*]] = icmp ugt i64 [[TMP0]], [[IDXPROM]]
// REC-NEXT: br i1 [[DOTNOT]], label %[[BB1:.*]], label %[[TRAP:.*]]
// REC: [[BB1]]:
// REC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[VLA]], i64 [[IDXPROM]]
// REC-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA8:![0-9]+]]
// REC-NEXT: ret double [[TMP2]]
// REC: [[TRAP]]:
// REC-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR7]], !nosanitize [[META2]]
// REC-NEXT: br label %[[BB1]], !nosanitize [[META2]]
//
double f1(int b, int i) {
double a[b];
use(a);
return a[i];
}

//.
// CHECK: [[META2]] = !{}
// CHECK: [[PROF3]] = !{!"branch_weights", i32 1, i32 1048575}
// CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
// CHECK: [[META5]] = !{!"int", [[META6:![0-9]+]], i64 0}
// CHECK: [[META6]] = !{!"omnipotent char", [[META7:![0-9]+]], i64 0}
// CHECK: [[META7]] = !{!"Simple C/C++ TBAA"}
// CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
// CHECK: [[META9]] = !{!"double", [[META6]], i64 0}
//.
// TR: [[META2]] = !{}
// TR: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0}
// TR: [[META4]] = !{!"int", [[META5:![0-9]+]], i64 0}
// TR: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0}
// TR: [[META6]] = !{!"Simple C/C++ TBAA"}
// TR: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
// TR: [[META8]] = !{!"double", [[META5]], i64 0}
//.
// REC: [[META2]] = !{}
// REC: [[PROF3]] = !{!"branch_weights", i32 1, i32 1048575}
// REC: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
// REC: [[META5]] = !{!"int", [[META6:![0-9]+]], i64 0}
// REC: [[META6]] = !{!"omnipotent char", [[META7:![0-9]+]], i64 0}
// REC: [[META7]] = !{!"Simple C/C++ TBAA"}
// REC: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
// REC: [[META9]] = !{!"double", [[META6]], i64 0}
//.
8 changes: 7 additions & 1 deletion llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ STATISTIC(ChecksAdded, "Bounds checks added");
STATISTIC(ChecksSkipped, "Bounds checks skipped");
STATISTIC(ChecksUnable, "Bounds checks unable to add");

using BuilderTy = IRBuilder<TargetFolder>;
class BuilderTy : public IRBuilder<TargetFolder> {
public:
BuilderTy(BasicBlock *TheBB, BasicBlock::iterator IP, TargetFolder Folder)
: IRBuilder<TargetFolder>(TheBB, IP, Folder) {
SetNoSanitizeMetadata();
}
};

/// Gets the conditions under which memory accessing instructions will overflow.
///
Expand Down
Loading
Loading