Skip to content

Commit c2aee50

Browse files
authored
[ubsan] Runtime and driver support for local-bounds (#120515)
Implements ``-f[no-]sanitize-trap=local-bounds``, and ``-f[no-]sanitize-recover=local-bounds``. LLVM part is here #120513.
1 parent 4420167 commit c2aee50

File tree

11 files changed

+63
-13
lines changed

11 files changed

+63
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,8 @@ Sanitizers
12061206
``-fsanitize=type`` flag. This sanitizer detects violations of C/C++ type-based
12071207
aliasing rules.
12081208

1209+
- Implemented ``-f[no-]sanitize-trap=local-bounds``, and ``-f[no-]sanitize-recover=local-bounds``.
1210+
12091211
Python Binding Changes
12101212
----------------------
12111213
- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,9 +1028,20 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
10281028
// of the pipeline.
10291029
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
10301030
PB.registerScalarOptimizerLateEPCallback(
1031-
[](FunctionPassManager &FPM, OptimizationLevel Level) {
1032-
FPM.addPass(
1033-
BoundsCheckingPass(BoundsCheckingPass::ReportingMode::Trap));
1031+
[this](FunctionPassManager &FPM, OptimizationLevel Level) {
1032+
BoundsCheckingPass::ReportingMode Mode;
1033+
if (CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) {
1034+
Mode = BoundsCheckingPass::ReportingMode::Trap;
1035+
} else if (CodeGenOpts.SanitizeMinimalRuntime) {
1036+
Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds)
1037+
? BoundsCheckingPass::ReportingMode::MinRuntime
1038+
: BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
1039+
} else {
1040+
Mode = CodeGenOpts.SanitizeRecover.has(SanitizerKind::LocalBounds)
1041+
? BoundsCheckingPass::ReportingMode::FullRuntime
1042+
: BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
1043+
}
1044+
FPM.addPass(BoundsCheckingPass(Mode));
10341045
});
10351046

10361047
// Don't add sanitizers if we are here from ThinLTO PostLink. That already

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ using namespace llvm::opt;
2727

2828
static const SanitizerMask NeedsUbsanRt =
2929
SanitizerKind::Undefined | SanitizerKind::Integer |
30-
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
31-
SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
32-
SanitizerKind::ObjCCast;
30+
SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |
31+
SanitizerKind::Nullability | SanitizerKind::CFI |
32+
SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
3333
static const SanitizerMask NeedsUbsanCxxRt =
3434
SanitizerKind::Vptr | SanitizerKind::CFI;
3535
static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
@@ -69,7 +69,8 @@ static const SanitizerMask TrappingSupported =
6969
SanitizerKind::LocalBounds | SanitizerKind::CFI |
7070
SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
7171
static const SanitizerMask MergeDefault = SanitizerKind::Undefined;
72-
static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
72+
static const SanitizerMask TrappingDefault =
73+
SanitizerKind::CFI | SanitizerKind::LocalBounds;
7374
static const SanitizerMask CFIClasses =
7475
SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
7576
SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |

clang/test/CodeGen/bounds-checking.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsanitize=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
22
// RUN: %clang_cc1 -fsanitize=array-bounds -O -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s
33
// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s
44
//

compiler-rt/lib/ubsan/ubsan_checks.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ UBSAN_CHECK(ImplicitSignedIntegerTruncationOrSignChange,
5353
UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base")
5454
UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent")
5555
UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds")
56+
UBSAN_CHECK(LocalOutOfBounds, "local-out-of-bounds", "local-bounds")
5657
UBSAN_CHECK(UnreachableCall, "unreachable-call", "unreachable")
5758
UBSAN_CHECK(MissingReturn, "missing-return", "return")
5859
UBSAN_CHECK(NonPositiveVLAIndex, "non-positive-vla-index", "vla-bound")

compiler-rt/lib/ubsan/ubsan_handlers.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,28 @@ void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
405405
Die();
406406
}
407407

408+
static void handleLocalOutOfBoundsImpl(ReportOptions Opts) {
409+
// FIXME: Pass more diagnostic info.
410+
SymbolizedStackHolder CallerLoc;
411+
CallerLoc.reset(getCallerLocation(Opts.pc));
412+
Location Loc;
413+
Loc = CallerLoc;
414+
ErrorType ET = ErrorType::LocalOutOfBounds;
415+
ScopedReport R(Opts, Loc, ET);
416+
Diag(Loc, DL_Error, ET, "access out of bounds");
417+
}
418+
419+
void __ubsan::__ubsan_handle_local_out_of_bounds() {
420+
GET_REPORT_OPTIONS(false);
421+
handleLocalOutOfBoundsImpl(Opts);
422+
}
423+
424+
void __ubsan::__ubsan_handle_local_out_of_bounds_abort() {
425+
GET_REPORT_OPTIONS(true);
426+
handleLocalOutOfBoundsImpl(Opts);
427+
Die();
428+
}
429+
408430
static void handleBuiltinUnreachableImpl(UnreachableData *Data,
409431
ReportOptions Opts) {
410432
ErrorType ET = ErrorType::UnreachableCall;

compiler-rt/lib/ubsan/ubsan_handlers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ struct OutOfBoundsData {
9090
/// \brief Handle an array index out of bounds error.
9191
RECOVERABLE(out_of_bounds, OutOfBoundsData *Data, ValueHandle Index)
9292

93+
/// \brief Handle an local object access out of bounds error.
94+
RECOVERABLE(local_out_of_bounds)
95+
9396
struct UnreachableData {
9497
SourceLocation Loc;
9598
};

compiler-rt/lib/ubsan/ubsan_interface.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ INTERFACE_FUNCTION(__ubsan_handle_nullability_return_v1)
4646
INTERFACE_FUNCTION(__ubsan_handle_nullability_return_v1_abort)
4747
INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds)
4848
INTERFACE_FUNCTION(__ubsan_handle_out_of_bounds_abort)
49+
INTERFACE_FUNCTION(__ubsan_handle_local_out_of_bounds)
50+
INTERFACE_FUNCTION(__ubsan_handle_local_out_of_bounds_abort)
4951
INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow)
5052
INTERFACE_FUNCTION(__ubsan_handle_pointer_overflow_abort)
5153
INTERFACE_FUNCTION(__ubsan_handle_shift_out_of_bounds)

compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ HANDLER(negate_overflow, "negate-overflow")
138138
HANDLER(divrem_overflow, "divrem-overflow")
139139
HANDLER(shift_out_of_bounds, "shift-out-of-bounds")
140140
HANDLER(out_of_bounds, "out-of-bounds")
141+
HANDLER(local_out_of_bounds, "local-out-of-bounds")
141142
HANDLER_RECOVER(builtin_unreachable, "builtin-unreachable")
142143
HANDLER_RECOVER(missing_return, "missing-return")
143144
HANDLER(vla_bound_not_positive, "vla-bound-not-positive")

compiler-rt/test/ubsan/TestCases/Misc/local_bounds.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && %run %t 1
22
// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && not --crash %run %t 3
3-
4-
// FIXME: it's always trap for now.
3+
// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds %s -O3 -o %t && not %run %t 3 2>&1 | FileCheck %s
4+
// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s
5+
// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds -g %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s --check-prefixes=LINE
56

67
#include <cstdlib>
78

@@ -14,12 +15,17 @@ __attribute__((noinline)) void init(S *s) {
1415
__asm__ __volatile__("" : : "r"(s) : "memory");
1516
}
1617

17-
__attribute__((noinline, no_sanitize("memory"))) int test(char i) {
18+
__attribute__((noinline, no_sanitize("memory", "address", "hwaddress"))) int
19+
test(char i) {
1820
S a;
1921
init(&a);
2022
S b;
2123
init(&b);
2224
return ((int *)(&a))[i];
25+
// CHECK: error: access out of bounds
26+
// CHECK: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
27+
// LINE: local_bounds.cpp:[[#@LINE-3]]:{{.*}}runtime error: access out of bounds
28+
// LINE: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}local_bounds.cpp:[[#@LINE-4]]:
2329
}
2430

2531
int main(int argc, char **argv) {

compiler-rt/test/ubsan_minimal/TestCases/local_bounds.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && %run %t 1
22
// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && not --crash %run %t 3
3-
4-
// FIXME: it's always trap for now.
3+
// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds %s -O3 -o %t && not --crash %run %t 3 2>&1 | FileCheck %s
4+
// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s
55

66
#include <cstdlib>
77

@@ -20,6 +20,7 @@ __attribute__((noinline, no_sanitize("memory"))) int test(char i) {
2020
S b;
2121
init(&b);
2222
return ((int *)(&a))[i];
23+
// CHECK: ubsan: local-out-of-bounds by 0x{{[[:xdigit:]]+$}}
2324
}
2425

2526
int main(int argc, char **argv) {

0 commit comments

Comments
 (0)