From beda8dd02727d0de55e2177269d3b85c45da69c5 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Sun, 29 Jun 2025 08:16:34 -0500 Subject: [PATCH] Core: Restructure sanitizers --- core/templates/rid_owner.h | 10 ---------- core/typedefs.h | 26 ++++++++++++++++++++++++++ drivers/unix/os_unix.cpp | 2 +- platform/linuxbsd/detect.py | 6 +++++- platform/linuxbsd/godot_linuxbsd.cpp | 4 ++-- platform/macos/detect.py | 4 +++- platform/macos/godot_main_macos.mm | 4 ++-- platform/web/detect.py | 3 +++ platform/windows/detect.py | 5 +++-- tests/core/object/test_object.h | 12 +----------- tests/core/templates/test_rid.h | 12 ------------ 11 files changed, 46 insertions(+), 42 deletions(-) diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h index c5e2b05868..f97a905b14 100644 --- a/core/templates/rid_owner.h +++ b/core/templates/rid_owner.h @@ -40,16 +40,6 @@ #include #include // IWYU pragma: keep // Used in macro. -#ifdef SANITIZERS_ENABLED -#ifdef __has_feature -#if __has_feature(thread_sanitizer) -#define TSAN_ENABLED -#endif -#elif defined(__SANITIZE_THREAD__) -#define TSAN_ENABLED -#endif -#endif - #ifdef TSAN_ENABLED #include #endif diff --git a/core/typedefs.h b/core/typedefs.h index 0928f8aaff..9bb710117c 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -56,6 +56,32 @@ static_assert(__cplusplus >= 201703L, "Minimum of C++17 required."); // IWYU pragma: end_exports +#if defined(__has_feature) +#define GD_HAS_FEATURE(m_feature) __has_feature(m_feature) +#else +#define GD_HAS_FEATURE(m_feature) 0 +#endif + +#if (GD_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) && !defined(ASAN_ENABLED) +#error Address sanitizer was enabled without defining `ASAN_ENABLED` +#endif + +#if (GD_HAS_FEATURE(leak_sanitizer) || defined(__SANITIZE_LEAKS__)) && !defined(LSAN_ENABLED) +#error Leak sanitizer was enabled without defining `LSAN_ENABLED` +#endif + +#if (GD_HAS_FEATURE(memory_sanitizer) || defined(__SANITIZE_MEMORY__)) && !defined(MSAN_ENABLED) +#error Memory sanitizer was enabled without defining `MSAN_ENABLED` +#endif + +#if (GD_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)) && !defined(TSAN_ENABLED) +#error Thread sanitizer was enabled without defining `TSAN_ENABLED` +#endif + +#if (GD_HAS_FEATURE(undefined_behavior_sanitizer) || defined(__UNDEFINED_SANITIZER__)) && !defined(UBSAN_ENABLED) +#error Undefined behavior sanitizer was enabled without defining `UBSAN_ENABLED` +#endif + // Turn argument to string constant: // https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing #ifndef _STR diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 044e9a0cf6..e89fc420d1 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -87,7 +87,7 @@ #define RTLD_DEEPBIND 0 #endif -#ifndef SANITIZERS_ENABLED +#ifndef ASAN_ENABLED #define GODOT_DLOPEN_MODE RTLD_NOW | RTLD_DEEPBIND #else #define GODOT_DLOPEN_MODE RTLD_NOW diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index e1e6886ac0..27a0fea586 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -144,9 +144,9 @@ def configure(env: "SConsEnvironment"): if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]: env.extra_suffix += ".san" - env.Append(CPPDEFINES=["SANITIZERS_ENABLED"]) if env["use_ubsan"]: + env.Append(CPPDEFINES=["UBSAN_ENABLED"]) env.Append( CCFLAGS=[ "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin" @@ -163,18 +163,22 @@ def configure(env: "SConsEnvironment"): env.Append(CCFLAGS=["-fsanitize=bounds-strict"]) if env["use_asan"]: + env.Append(CPPDEFINES=["ASAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_lsan"]: + env.Append(CPPDEFINES=["LSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=leak"]) env.Append(LINKFLAGS=["-fsanitize=leak"]) if env["use_tsan"]: + env.Append(CPPDEFINES=["TSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=thread"]) env.Append(LINKFLAGS=["-fsanitize=thread"]) if env["use_msan"] and env["use_llvm"]: + env.Append(CPPDEFINES=["MSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=memory"]) env.Append(CCFLAGS=["-fsanitize-memory-track-origins"]) env.Append(CCFLAGS=["-fsanitize-recover=memory"]) diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp index acfd4d952e..1b18e6ba02 100644 --- a/platform/linuxbsd/godot_linuxbsd.cpp +++ b/platform/linuxbsd/godot_linuxbsd.cpp @@ -38,7 +38,7 @@ #include #include -#if defined(SANITIZERS_ENABLED) +#if defined(ASAN_ENABLED) #include #endif @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { } #endif -#if defined(SANITIZERS_ENABLED) +#if defined(ASAN_ENABLED) // Note: Set stack size to be at least 30 MB (vs 8 MB default) to avoid overflow, address sanitizer can increase stack usage up to 3 times. struct rlimit stack_lim = { 0x1E00000, 0x1E00000 }; setrlimit(RLIMIT_STACK, &stack_lim); diff --git a/platform/macos/detect.py b/platform/macos/detect.py index cfedad0970..f9685cb4fe 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -154,9 +154,9 @@ def configure(env: "SConsEnvironment"): if env["use_ubsan"] or env["use_asan"] or env["use_tsan"]: env.extra_suffix += ".san" - env.Append(CPPDEFINES=["SANITIZERS_ENABLED"]) if env["use_ubsan"]: + env.Append(CPPDEFINES=["UBSAN_ENABLED"]) env.Append( CCFLAGS=[ "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin" @@ -166,10 +166,12 @@ def configure(env: "SConsEnvironment"): env.Append(CCFLAGS=["-fsanitize=nullability-return,nullability-arg,function,nullability-assign"]) if env["use_asan"]: + env.Append(CPPDEFINES=["ASAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_tsan"]: + env.Append(CPPDEFINES=["TSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=thread"]) env.Append(LINKFLAGS=["-fsanitize=thread"]) diff --git a/platform/macos/godot_main_macos.mm b/platform/macos/godot_main_macos.mm index 46dc949557..0a0732743e 100644 --- a/platform/macos/godot_main_macos.mm +++ b/platform/macos/godot_main_macos.mm @@ -35,7 +35,7 @@ #include "core/profiling/profiling.h" #include "main/main.h" -#if defined(SANITIZERS_ENABLED) +#if defined(ASAN_ENABLED) #include #endif @@ -47,7 +47,7 @@ int main(int argc, char **argv) { setenv("MVK_CONFIG_SWAPCHAIN_MIN_MAG_FILTER_USE_NEAREST", "0", 1); // MoltenVK - use linear surface scaling. TODO: remove when full DPI scaling is implemented. #endif -#if defined(SANITIZERS_ENABLED) +#if defined(ASAN_ENABLED) // Note: Set stack size to be at least 30 MB (vs 8 MB default) to avoid overflow, address sanitizer can increase stack usage up to 3 times. struct rlimit stack_lim = { 0x1E00000, 0x1E00000 }; setrlimit(RLIMIT_STACK, &stack_lim); diff --git a/platform/web/detect.py b/platform/web/detect.py index 49dc2c50f5..d8211068b2 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -183,12 +183,15 @@ def configure(env: "SConsEnvironment"): # Sanitizers if env["use_ubsan"]: + env.Append(CPPDEFINES=["UBSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=undefined"]) env.Append(LINKFLAGS=["-fsanitize=undefined"]) if env["use_asan"]: + env.Append(CPPDEFINES=["ASAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=address"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_lsan"]: + env.Append(CPPDEFINES=["LSAN_ENABLED"]) env.Append(CCFLAGS=["-fsanitize=leak"]) env.Append(LINKFLAGS=["-fsanitize=leak"]) if env["use_safe_heap"]: diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 011cdade4c..c8d3334294 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -375,7 +375,7 @@ def configure_msvc(env: "SConsEnvironment"): if env["use_asan"]: env.extra_suffix += ".san" prebuilt_lib_extra_suffix = ".san" - env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"]) + env.Append(CPPDEFINES=["ASAN_ENABLED"]) env.Append(CCFLAGS=["/fsanitize=address"]) env.Append(LINKFLAGS=["/INFERASANLIBS"]) @@ -730,11 +730,12 @@ def configure_mingw(env: "SConsEnvironment"): sys.exit(255) env.extra_suffix += ".san" - env.AppendUnique(CPPDEFINES=["SANITIZERS_ENABLED"]) san_flags = [] if env["use_asan"]: + env.Append(CPPDEFINES=["ASAN_ENABLED"]) san_flags.append("-fsanitize=address") if env["use_ubsan"]: + env.Append(CPPDEFINES=["UBSAN_ENABLED"]) san_flags.append("-fsanitize=undefined") # Disable the vptr check since it gets triggered on any COM interface calls. san_flags.append("-fno-sanitize=vptr") diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h index e683568a56..89fa5fa88b 100644 --- a/tests/core/object/test_object.h +++ b/tests/core/object/test_object.h @@ -36,16 +36,6 @@ #include "tests/test_macros.h" -#ifdef SANITIZERS_ENABLED -#ifdef __has_feature -#if __has_feature(address_sanitizer) || __has_feature(thread_sanitizer) -#define ASAN_OR_TSAN_ENABLED -#endif -#elif defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) -#define ASAN_OR_TSAN_ENABLED -#endif -#endif - // Declared in global namespace because of GDCLASS macro warning (Windows): // "Unqualified friend declaration referring to type outside of the nearest enclosing namespace // is a Microsoft extension; add a nested name specifier". @@ -605,7 +595,7 @@ TEST_CASE("[Object] Destruction at the end of the call chain is safe") { // This has to be static because ~Object() also destroys the script instance. static void free_self(Object *p_self) { -#if defined(ASAN_OR_TSAN_ENABLED) +#if defined(ASAN_ENABLED) || defined(TSAN_ENABLED) // Regular deletion is enough becausa asan/tsan will catch a potential heap-after-use. memdelete(p_self); #else diff --git a/tests/core/templates/test_rid.h b/tests/core/templates/test_rid.h index ed0f194760..b8bdf8167b 100644 --- a/tests/core/templates/test_rid.h +++ b/tests/core/templates/test_rid.h @@ -37,18 +37,6 @@ #include "tests/test_macros.h" -#ifdef THREADS_ENABLED -#ifdef SANITIZERS_ENABLED -#ifdef __has_feature -#if __has_feature(thread_sanitizer) -#define TSAN_ENABLED -#endif -#elif defined(__SANITIZE_THREAD__) -#define TSAN_ENABLED -#endif -#endif // SANITIZERS_ENABLED -#endif // THREADS_ENABLED - #ifdef TSAN_ENABLED #include #endif