From a5fb057dd9a7cdc777f0ce940d3e28421dbb5a4a Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Tue, 18 Nov 2025 17:36:02 -0800 Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.7 [skip ci] --- .../ubsan_minimal/ubsan_minimal_handlers.cpp | 19 +++++++++++++++++++ .../TestCases/test-darwin-interface.c | 1 + 2 files changed, 20 insertions(+) diff --git a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp index a2a2e36e8523d..0a2d6f35a539a 100644 --- a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp +++ b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp @@ -89,6 +89,17 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind, } } +SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_preserve, + const char *kind, uintptr_t caller, + const uintptr_t *address) +[[clang::preserve_all]] { + // Additional indirecton so the user can override this with their own + // preserve_all function. This would allow, e.g., a function that reports the + // first error only, so for all subsequent calls we can skip the register save + // / restore. + __ubsan_report_error(kind, caller, address); +} + SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind, uintptr_t caller, const uintptr_t *address) { // Use another handlers, in case it's already overriden. @@ -130,6 +141,10 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) { #define HANDLER_RECOVER(name, kind) \ INTERFACE void __ubsan_handle_##name##_minimal() { \ __ubsan_report_error(kind, GET_CALLER_PC(), nullptr); \ + } \ + INTERFACE void __ubsan_handle_##name##_minimal_preserve() \ + [[clang::preserve_all]] { \ + __ubsan_report_error_preserve(kind, GET_CALLER_PC(), nullptr); \ } #define HANDLER_NORECOVER(name, kind) \ @@ -146,6 +161,10 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) { #define HANDLER_RECOVER_PTR(name, kind) \ INTERFACE void __ubsan_handle_##name##_minimal(const uintptr_t address) { \ __ubsan_report_error(kind, GET_CALLER_PC(), &address); \ + } \ + INTERFACE void __ubsan_handle_##name##_minimal_preserve( \ + const uintptr_t address) [[clang::preserve_all]] { \ + __ubsan_report_error_preserve(kind, GET_CALLER_PC(), &address); \ } #define HANDLER_NORECOVER_PTR(name, kind) \ diff --git a/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c b/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c index abc1073e02073..3c76e5aadc087 100644 --- a/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c +++ b/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c @@ -4,6 +4,7 @@ // REQUIRES: x86_64-darwin // RUN: nm -jgU `%clangxx_min_runtime -fsanitize-minimal-runtime -fsanitize=undefined %s -o %t '-###' 2>&1 | grep "libclang_rt.ubsan_minimal_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.ubsan_minimal_osx_dynamic.dylib\)".*/\1/'` | grep "^___ubsan_handle" \ +// RUN: | grep -vE "_minimal_preserve" \ // RUN: | sed 's/_minimal//g' \ // RUN: > %t.minimal.symlist // From d2231031d7ecfffc97709d6bf2236ead4147aab8 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Wed, 19 Nov 2025 18:01:59 -0800 Subject: [PATCH 2/4] rename Created using spr 1.3.7 --- clang/include/clang/Basic/CodeGenOptions.def | 2 +- clang/include/clang/Driver/SanitizerArgs.h | 2 +- clang/include/clang/Options/Options.td | 6 +++--- clang/lib/Driver/SanitizerArgs.cpp | 11 ++++++----- clang/test/Driver/fsanitize.c | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 3c9cdf5545c1f..76a6463881c6f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -270,7 +270,7 @@ CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0, Benign) ///< Enable use-after-delet CODEGENOPT(SanitizeCfiCrossDso, 1, 0, Benign) ///< Enable cross-dso support in CFI. CODEGENOPT(SanitizeMinimalRuntime, 1, 0, Benign) ///< Use "_minimal" sanitizer runtime for ///< diagnostics. -CODEGENOPT(SanitizePreserveRuntime, 1, 0, Benign) ///< Use "_preserve" sanitizer runtime for +CODEGENOPT(SanitizeHandlerPreserveAllRegs, 1, 0, Benign) ///< Use "_preserve" sanitizer runtime for ///< diagnostics. CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0, Benign) ///< Generalize pointer types in ///< CFI icall function signatures diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index eef482cb577a9..6fd059263fb4d 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -67,7 +67,7 @@ class SanitizerArgs { bool TsanFuncEntryExit = true; bool TsanAtomics = true; bool MinimalRuntime = false; - bool PreserveRuntime = false; + bool HandlerPreserveAllRegs = false; // True if cross-dso CFI support if provided by the system (i.e. Android). bool ImplicitCfiRuntime = false; bool NeedsMemProfRt = false; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index a3e0566d9763d..2c9876c305ffe 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2656,9 +2656,9 @@ defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime", PosFlag, NegFlag>, Group; -defm sanitize_preserve_runtime - : BoolOption<"f", "sanitize-preserve-runtime", - CodeGenOpts<"SanitizePreserveRuntime">, DefaultFalse, +defm sanitize_handler_preserve_all_regs_experimental + : BoolOption<"f", "sanitize-handler-preserve-all-regs-experimental", + CodeGenOpts<"SanitizeHandlerPreserveAllRegs">, DefaultFalse, PosFlag, NegFlag>, Group; def fsanitize_link_runtime : Flag<["-"], "fsanitize-link-runtime">, diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index c5ef3018b2455..42d3f52e2de9f 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -423,9 +423,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, MinimalRuntime = Args.hasFlag(options::OPT_fsanitize_minimal_runtime, options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime); - PreserveRuntime = - Args.hasFlag(options::OPT_fsanitize_preserve_runtime, - options::OPT_fno_sanitize_preserve_runtime, PreserveRuntime); + HandlerPreserveAllRegs = Args.hasFlag( + options::OPT_fsanitize_handler_preserve_all_regs_experimental, + options::OPT_fno_sanitize_handler_preserve_all_regs_experimental, + HandlerPreserveAllRegs); // The object size sanitizer should not be enabled at -O0. Arg *OptLevel = Args.getLastArg(options::OPT_O_Group); @@ -1472,8 +1473,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, if (MinimalRuntime) CmdArgs.push_back("-fsanitize-minimal-runtime"); - if (PreserveRuntime) - CmdArgs.push_back("-fsanitize-preserve-runtime"); + if (HandlerPreserveAllRegs) + CmdArgs.push_back("-fsanitize-handler-preserve-all-regs-experimental"); if (AsanFieldPadding) CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 03241c2fcf91a..18f2b74b7b580 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -984,10 +984,10 @@ // CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime -fsanitize-preserve-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL-PRESERVE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime -fsanitize-handler-preserve-all-regs-experimental %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL-PRESERVE // CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-minimal-runtime" -// CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-preserve-runtime" +// CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-handler-preserve-all-regs-experimental" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=integer -fsanitize-trap=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTSAN-TRAP // CHECK-INTSAN-TRAP: "-fsanitize-trap=integer-divide-by-zero,shift-base,shift-exponent,signed-integer-overflow,unsigned-integer-overflow,unsigned-shift-base,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change" From 5a7c143d885af5aa333ddf3473242f857204684a Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Wed, 19 Nov 2025 18:18:30 -0800 Subject: [PATCH 3/4] rename Created using spr 1.3.7 --- clang/include/clang/Options/Options.td | 4 ++-- clang/lib/Driver/SanitizerArgs.cpp | 10 +++++----- clang/test/Driver/fsanitize.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 2c9876c305ffe..9650e99754cd7 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2656,8 +2656,8 @@ defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime", PosFlag, NegFlag>, Group; -defm sanitize_handler_preserve_all_regs_experimental - : BoolOption<"f", "sanitize-handler-preserve-all-regs-experimental", +defm sanitize_handler_preserve_all_regs + : BoolOption<"f", "sanitize-handler-preserve-all-regs", CodeGenOpts<"SanitizeHandlerPreserveAllRegs">, DefaultFalse, PosFlag, NegFlag>, Group; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 42d3f52e2de9f..10f85b6bd1651 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -423,10 +423,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, MinimalRuntime = Args.hasFlag(options::OPT_fsanitize_minimal_runtime, options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime); - HandlerPreserveAllRegs = Args.hasFlag( - options::OPT_fsanitize_handler_preserve_all_regs_experimental, - options::OPT_fno_sanitize_handler_preserve_all_regs_experimental, - HandlerPreserveAllRegs); + HandlerPreserveAllRegs = + Args.hasFlag(options::OPT_fsanitize_handler_preserve_all_regs, + options::OPT_fno_sanitize_handler_preserve_all_regs, + HandlerPreserveAllRegs); // The object size sanitizer should not be enabled at -O0. Arg *OptLevel = Args.getLastArg(options::OPT_O_Group); @@ -1474,7 +1474,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back("-fsanitize-minimal-runtime"); if (HandlerPreserveAllRegs) - CmdArgs.push_back("-fsanitize-handler-preserve-all-regs-experimental"); + CmdArgs.push_back("-fsanitize-handler-preserve-all-regs"); if (AsanFieldPadding) CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 18f2b74b7b580..f2a4d8c50ec23 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -984,10 +984,10 @@ // CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime -fsanitize-handler-preserve-all-regs-experimental %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL-PRESERVE +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime -fsanitize-handler-preserve-all-regs %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL-PRESERVE // CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-minimal-runtime" -// CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-handler-preserve-all-regs-experimental" +// CHECK-UBSAN-MINIMAL-PRESERVE: "-fsanitize-handler-preserve-all-regs // RUN: %clang --target=x86_64-linux-gnu -fsanitize=integer -fsanitize-trap=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTSAN-TRAP // CHECK-INTSAN-TRAP: "-fsanitize-trap=integer-divide-by-zero,shift-base,shift-exponent,signed-integer-overflow,unsigned-integer-overflow,unsigned-shift-base,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change" From 145118df1c2c641e3dbb9e3bd7859705b368ee76 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Thu, 20 Nov 2025 14:56:54 -0800 Subject: [PATCH 4/4] help Created using spr 1.3.7 --- clang/include/clang/Options/Options.td | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 9650e99754cd7..1e713a1b06943 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2657,9 +2657,13 @@ defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime", NegFlag>, Group; defm sanitize_handler_preserve_all_regs - : BoolOption<"f", "sanitize-handler-preserve-all-regs", - CodeGenOpts<"SanitizeHandlerPreserveAllRegs">, DefaultFalse, - PosFlag, NegFlag>, + : BoolOption< + "f", "sanitize-handler-preserve-all-regs", + CodeGenOpts<"SanitizeHandlerPreserveAllRegs">, DefaultFalse, + PosFlag, + NegFlag>, Group; def fsanitize_link_runtime : Flag<["-"], "fsanitize-link-runtime">, Group;