Core: Restructure sanitizers

This commit is contained in:
Thaddeus Crews 2025-06-29 08:16:34 -05:00
parent 77579f93e6
commit beda8dd027
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
11 changed files with 46 additions and 42 deletions

View file

@ -40,16 +40,6 @@
#include <cstdio>
#include <typeinfo> // 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 <sanitizer/tsan_interface.h>
#endif

View file

@ -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

View file

@ -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

View file

@ -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"])

View file

@ -38,7 +38,7 @@
#include <clocale>
#include <cstdlib>
#if defined(SANITIZERS_ENABLED)
#if defined(ASAN_ENABLED)
#include <sys/resource.h>
#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);

View file

@ -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"])

View file

@ -35,7 +35,7 @@
#include "core/profiling/profiling.h"
#include "main/main.h"
#if defined(SANITIZERS_ENABLED)
#if defined(ASAN_ENABLED)
#include <sys/resource.h>
#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);

View file

@ -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"]:

View file

@ -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")

View file

@ -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

View file

@ -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 <sanitizer/tsan_interface.h>
#endif