From 7e271d0adc9f03ad82cc255af312d983c22c3653 Mon Sep 17 00:00:00 2001 From: nasr <156965421+div0rce@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:15:39 -0400 Subject: [PATCH] fix(ci): make the UBSan gate abort on error (-fno-sanitize-recover=undefined) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-2 bug hunt found the asan preset's UBSan half was non-functional. The preset compiles with -fsanitize=address,undefined but never sets -fno-sanitize-recover=undefined or UBSAN_OPTIONS=halt_on_error=1, and UBSan defaults to RECOVER mode: on a violation it prints a diagnostic and CONTINUES, with the process still exiting 0. Catch2 tests pass/fail on the process exit code, so any pure-UBSan defect (signed overflow, invalid enum/bool load, out-of-range shift, misaligned/null pointer arithmetic) printed a warning yet the test PASSED and `make asan` / the CI sanitizers job stayed green. ASan still aborts on memory errors and TSan still exits non-zero on a race, so only the UBSan half of the hardening gate was broken — precisely the class of UB the repo's own enum-domain decoder hardening (#136) relies on the gate to catch. Fix: add -fno-sanitize-recover=undefined to the QSL_ENABLE_ASAN compile options so UBSan aborts on the first violation (and `make asan` fails locally, not just in CI). Verified: with the flag, a signed-overflow program exits non-zero (gate works); the existing tree is UBSan-clean (make asan still 270/270), so the gate was simply not enforcing, not masking live bugs. Co-Authored-By: Claude Opus 4.8 --- cmake/Sanitizers.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake index 491e1fd..a174e8b 100644 --- a/cmake/Sanitizers.cmake +++ b/cmake/Sanitizers.cmake @@ -7,7 +7,14 @@ if(QSL_ENABLE_ASAN AND QSL_ENABLE_TSAN) endif() if(QSL_ENABLE_ASAN) - add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer) + # -fno-sanitize-recover=undefined makes UBSan ABORT on the first violation instead of its default + # "recover" mode (print a diagnostic and continue, with the process still exiting 0). Without it + # the UBSan half of this gate is non-functional: a pure-UBSan defect (signed overflow, invalid + # enum/bool load, out-of-range shift, misaligned/null pointer arithmetic) prints a warning but the + # test still PASSES, so `make asan` and the CI sanitizers job stay green. ASan already aborts on + # memory errors by default; this brings UBSan to parity. + add_compile_options(-fsanitize=address,undefined -fno-sanitize-recover=undefined + -fno-omit-frame-pointer) add_link_options(-fsanitize=address,undefined) endif()