cleanup and additions to asan, ubsan suppressions

Signed-off-by: Pratik Mankawde <pratikmankawde@gmail.com>
This commit is contained in:
Pratik Mankawde
2025-11-21 16:24:38 +00:00
parent 32d129ee5e
commit facb6c63e3
10 changed files with 175 additions and 101 deletions

View File

@@ -22,9 +22,9 @@ inputs:
required: false
default: "verbose"
sanitizers:
description: "The sanitizers to enable ('None', 'Address', 'Thread')."
description: "The sanitizers to enable ('Address', 'Thread')."
required: false
default: "None"
default: ""
runs:
using: composite

View File

@@ -166,9 +166,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
# Use large code model to avoid relocation errors with large binaries
# Only for x86-64 (amd64) - ARM64 doesn't support -mcmodel=large
if architecture['platform'] == 'linux/amd64' and os['compiler_name'] == 'gcc':
# Add -mcmodel=large and -fPIC to both compiler AND linker flags
# This is needed because sanitizers create very large binaries
# -fPIC enables position independent code to avoid relocation range issues
# Add -mcmodel=large to both compiler AND linker flags
# This is needed because sanitizers create very large binaries and
# large model removes the 2GB limitation that medium model has
cxx_flags += ' -mcmodel=large -fno-PIC'
linker_relocation_flags+=' -mcmodel=large -fno-PIC'
@@ -211,38 +210,42 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
'architecture': architecture,
'sanitizers': 'Address'
})
# Since TSAN runs are crashing with seg faults(could be compatibility issues with latest compilers)
# We deactivate it for now. But I would keep the code, since it took some effort to find the correct set of config needed to run this.
# This will be useful when we decide to activate it again in future.
activateTSAN = False
if activateTSAN:
linker_flags = ''
# Update configs for tsan
# gcc doesn't supports atomic_thread_fence with tsan. Suppress warnings.
# Also tsan doesn't work well with mcmode=large and bfd linker
if os['compiler_name'] == 'gcc':
extra_warning_flags += ' -Wno-tsan'
cxx_flags = cxx_flags.replace('-mcmodel=large', '-mcmodel=medium')
linker_relocation_flags = linker_relocation_flags.replace('-mcmodel=large', '-mcmodel=medium')
# Add linker flags for Sanitizers
linker_flags += f' -DCMAKE_EXE_LINKER_FLAGS="{linker_relocation_flags} -fsanitize=thread,{sanitizers_flags}"'
linker_flags += f' -DCMAKE_SHARED_LINKER_FLAGS="{linker_relocation_flags} -fsanitize=thread,{sanitizers_flags}"'
elif os['compiler_name'] == 'clang':
# Note: We use $GITHUB_WORKSPACE environment variable which will be expanded by the shell
# before CMake processes it. This ensures the compiler receives an absolute path.
# CMAKE_SOURCE_DIR won't work here because it's inside CMAKE_CXX_FLAGS string.
cxx_flags += ' -fsanitize-ignorelist=$GITHUB_WORKSPACE/external/sanitizer-ignorelist.txt'
linker_flags += f' -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread,{sanitizers_flags}"'
linker_flags += f' -DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=thread,{sanitizers_flags}"'
linker_flags = ''
# Update configs for tsan
# gcc doesn't supports atomic_thread_fence with tsan. Suppress warnings.
# Also tsan doesn't work well with mcmode=large and bfd linker
if os['compiler_name'] == 'gcc':
extra_warning_flags += ' -Wno-tsan'
cxx_flags = cxx_flags.replace('-mcmodel=large', '-mcmodel=medium')
linker_relocation_flags = linker_relocation_flags.replace('-mcmodel=large', '-mcmodel=medium')
# Add linker flags for Sanitizers
linker_flags += f' -DCMAKE_EXE_LINKER_FLAGS="{linker_relocation_flags} -fsanitize=thread,{sanitizers_flags}"'
linker_flags += f' -DCMAKE_SHARED_LINKER_FLAGS="{linker_relocation_flags} -fsanitize=thread,{sanitizers_flags}"'
elif os['compiler_name'] == 'clang':
cxx_flags += ' -fsanitize-blacklist=$GITHUB_WORKSPACE/external/sanitizer-blacklist.txt'
linker_flags += f' -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=thread,{sanitizers_flags}"'
linker_flags += f' -DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=thread,{sanitizers_flags}"'
cmake_args_flags = f'{cmake_args} -DCMAKE_CXX_FLAGS="-fsanitize=thread,{sanitizers_flags} -fno-omit-frame-pointer {cxx_flags} {extra_warning_flags}" {linker_flags}'
# Note: We use $GITHUB_WORKSPACE environment variable which will be expanded by the shell
# before CMake processes it. This ensures the compiler receives an absolute path.
# CMAKE_SOURCE_DIR won't work here because it's inside CMAKE_CXX_FLAGS string.
cmake_args_flags = f'{cmake_args} -DCMAKE_CXX_FLAGS="-fsanitize=thread,{sanitizers_flags} -fno-omit-frame-pointer {cxx_flags} {extra_warning_flags}" {linker_flags}'
configurations.append({
'config_name': config_name+ "_tsan",
'cmake_args': cmake_args_flags,
'cmake_target': cmake_target,
'build_only': build_only,
'build_type': build_type,
'os': os,
'architecture': architecture,
'sanitizers': 'Thread'
})
configurations.append({
'config_name': config_name+ "_tsan",
'cmake_args': cmake_args_flags,
'cmake_target': cmake_target,
'build_only': build_only,
'build_type': build_type,
'os': os,
'architecture': architecture,
'sanitizers': 'Thread'
})
else:
if cxx_flags:
cmake_args_flags = f'{cmake_args} -DCMAKE_CXX_FLAGS={cxx_flags}'

View File

@@ -172,7 +172,7 @@ jobs:
BUILD_TYPE: ${{ inputs.build_type }}
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
run: |
export ASAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/asan.supp"
export ASAN_OPTIONS="detect_container_overflow=0 suppressions=$GITHUB_WORKSPACE/external/asan.supp"
export TSAN_OPTIONS="second_deadlock_stack=1 halt_on_error=0 suppressions=$GITHUB_WORKSPACE/external/tsan.supp"
export UBSAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/ubsan.supp"
export LSAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/lsan.supp"
@@ -187,7 +187,7 @@ jobs:
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: |
export ASAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/asan.supp"
export ASAN_OPTIONS="detect_container_overflow=0 suppressions=$GITHUB_WORKSPACE/external/asan.supp"
export TSAN_OPTIONS="second_deadlock_stack=1 halt_on_error=0 suppressions=$GITHUB_WORKSPACE/external/tsan.supp"
export UBSAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/ubsan.supp"
export LSAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/external/lsan.supp"

View File

@@ -362,7 +362,8 @@ tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS']
If you would like to activate `asan+ubsan`(`Address`) or `tsan+ubsan`(`Thread`) for the build,
declare an env. variable as follows and simply use the `sanitizers`
profile in the `conan install` command.
profile in the `conan install` command. Make sure you clear your conan cache before doing so.
Command: `conan cache clean "*"`
```
SANITIZERS=Address conan install .. --output-folder . --profile sanitizers --build missing --settings build_type=Debug

View File

@@ -3,10 +3,7 @@ include(default)
{% set default_sanitizer_flags = "undefined,float-divide-by-zero,signed-integer-overflow" %}
{% set sanitizers = os.getenv("SANITIZERS") %}
[settings]
[conf]
{% if sanitizers == "Address" or sanitizers == "Thread" %}
user.package:sanitizers={{ sanitizers }}
tools.info.package_id:confs+=["user.package:sanitizers"]
@@ -44,7 +41,6 @@ tools.build:cxxflags+=['{{tsan_sanitizer_flags}} -fno-omit-frame-pointer -O1']
tools.build:sharedlinkflags+=['{{tsan_sanitizer_flags}}']
tools.build:exelinkflags+=['{{tsan_sanitizer_flags}}']
{% endif %}
{% endif %}

39
external/asan.supp vendored
View File

@@ -1,16 +1,33 @@
# Suppress voilations in Boost libraries
interceptor_via_lib:^libboost_.*
# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions.
#
# ASAN_OPTIONS="detect_container_overflow=0:suppressions=external/asan.supp:halt_on_error=0"
#
# The detect_container_overflow=0 option disables false positives from:
# - Boost intrusive containers (slist_iterator.hpp, hashtable.hpp, aged_unordered_container.h)
# - Boost context/coroutine stack switching (Workers.cpp, thread.h)
#
# See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
# Suprpress voilations in external code
interceptor_name:^external/.*
interceptor_name:^external
# Boost
interceptor_name:.*/boost/asio/.*
interceptor_name:boost/asio
# Leaks in Doctests
interceptor_name:.*/src/libxrpl/net/HTTPClient.cpp
interceptor_name:.*/src/libxrpl/net/RegisterSSLCerts.cpp
interceptor_name:.*/src/tests/libxrpl/net/HTTPClient.cpp
interceptor_name:.*/xrpl/net/AutoSocket.h
interceptor_name:.*/xrpl/net/HTTPClient.h
interceptor_name:.*/xrpl/net/HTTPClientSSLContext.h
interceptor_name:.*/xrpl/net/RegisterSSLCerts.h
interceptor_name:src/libxrpl/net/HTTPClient.cpp
interceptor_name:src/libxrpl/net/RegisterSSLCerts.cpp
interceptor_name:src/tests/libxrpl/net/HTTPClient.cpp
interceptor_name:xrpl/net/AutoSocket.h
interceptor_name:xrpl/net/HTTPClient.h
interceptor_name:xrpl/net/HTTPClientSSLContext.h
interceptor_name:xrpl/net/RegisterSSLCerts.h
# Suppress false positive stack-buffer errors in thread stack allocation
# Related to ASan's __asan_handle_no_return warnings (github.com/google/sanitizers/issues/189)
# These occur during multi-threaded test initialization on macOS
interceptor_name:memcpy
interceptor_name:__bzero
interceptor_name:__asan_memset
interceptor_name:__asan_memcpy

22
external/lsan.supp vendored
View File

@@ -1,12 +1,16 @@
leak:.*/src/libxrpl/net/HTTPClient.cpp
leak:.*/src/libxrpl/net/RegisterSSLCerts.cpp
leak:.*/src/tests/libxrpl/net/HTTPClient.cpp
leak:.*/xrpl/net/AutoSocket.h
leak:.*/xrpl/net/HTTPClient.h
leak:.*/xrpl/net/HTTPClientSSLContext.h
leak:.*/xrpl/net/RegisterSSLCerts.h
# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions.
# Suppress leaks detected by asan in rippled code.
leak:src/libxrpl/net/HTTPClient.cpp
leak:src/libxrpl/net/RegisterSSLCerts.cpp
leak:src/tests/libxrpl/net/HTTPClient.cpp
leak:xrpl/net/AutoSocket.h
leak:xrpl/net/HTTPClient.h
leak:xrpl/net/HTTPClientSSLContext.h
leak:xrpl/net/RegisterSSLCerts.h
leak:ripple::HTTPClient
leak:ripple::HTTPClientImp
leak:.*boost::asio::.*
leak:.*/boost/asio/.*
# Suppress leaks detected by asan in boost code.
leak:boost::asio
leak:boost/asio

View File

@@ -1,26 +1,27 @@
[thread]
signal:libxrpl/beast/utility/beast_Journal.cpp
signal:libxrpl/beast/utility/beast_PropertyStream.cpp
signal:test/beast/beast_PropertyStream_test.cpp
signal:libxrpl/beast/utility/beast_Journal.cpp
signal:xrpld/core/detail/Workers.cpp
signal:xrpld/core/JobQueue.cpp
race:libxrpl/beast/utility/beast_Journal.cpp
race:libxrpl/beast/utility/beast_PropertyStream.cpp
race:test/beast/beast_PropertyStream_test.cpp
race:libxrpl/beast/utility/beast_Journal.cpp
race:xrpld/core/detail/Workers.cpp
race:xrpld/core/JobQueue.cpp
deadlock:libxrpl/beast/utility/beast_Journal.cpp
deadlock:libxrpl/beast/utility/beast_Journal.cpp
deadlock:libxrpl/beast/utility/beast_PropertyStream.cpp
deadlock:test/beast/beast_PropertyStream_test.cpp
deadlock:libxrpl/beast/utility/beast_Journal.cpp
deadlock:xrpld/core/detail/Workers.cpp
deadlock:xrpld/core/JobQueue.cpp
[tsan]
race:libxrpl/beast/utility/beast_Journal.cpp
race:libxrpl/beast/utility/beast_Journal.cpp
race:libxrpl/beast/utility/beast_PropertyStream.cpp
race:test/beast/beast_PropertyStream_test.cpp
race:xrpld/core/detail/Workers.cpp
race:xrpld/core/JobQueue.cpp
signal:libxrpl/beast/utility/beast_Journal.cpp
signal:libxrpl/beast/utility/beast_Journal.cpp
signal:libxrpl/beast/utility/beast_PropertyStream.cpp
signal:test/beast/beast_PropertyStream_test.cpp
signal:xrpld/core/detail/Workers.cpp
signal:xrpld/core/JobQueue.cpp
src:beast/utility/beast_Journal.cpp
src:beast/utility/beast_PropertyStream.cpp
src:test/beast/beast_PropertyStream_test.cpp
src:core/detail/Workers.cpp
src:core/JobQueue.cpp
src:core/JobQueue.cpp
src:libxrpl/beast/utility/beast_Journal.cpp
src:test/beast/beast_PropertyStream_test.cpp

30
external/tsan.supp vendored
View File

@@ -1,3 +1,5 @@
# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions.
# Suppress race in Boost ASIO scheduler detected by GCC-15
# This is a false positive in Boost's internal pipe() synchronization
race:boost/asio/
@@ -5,6 +7,7 @@ race:boost/context/
race:boost/asio/executor.hpp
race:boost::asio
# Suppress tsan related issues in rippled code.
race:src/libxrpl/basics/make_SSLContext.cpp
race:src/libxrpl/basics/Number.cpp
race:src/libxrpl/json/json_value.cpp
@@ -43,10 +46,11 @@ race:xrpl/server/detail/ServerImpl.h
race:xrpl/nodestore/detail/DatabaseNodeImp.h
race:src/libxrpl/beast/utility/beast_Journal.cpp
race:src/test/beast/LexicalCast_test.cpp
race:ripple::ServerHandler
# More suppressions in external library code.
race:crtstuff.c
race:pipe
race:ripple::ServerHandler
# Deadlock / lock-order-inversion suppressions
# Note: GCC's TSAN may not fully support all deadlock suppression patterns
@@ -54,17 +58,6 @@ deadlock:src/libxrpl/beast/utility/beast_Journal.cpp
deadlock:src/libxrpl/beast/utility/beast_PropertyStream.cpp
deadlock:src/test/beast/beast_PropertyStream_test.cpp
deadlock:src/xrpld/core/detail/Workers.cpp
# Suppress lock-order-inversion in recursive_mutex operations
deadlock:std::recursive_mutex::lock
deadlock:__gthread_recursive_mutex_lock
deadlock:pthread_mutex_lock
# Aggressive suppressing of deadlock tsan errors
deadlock:pthread_create
deadlock:pthread_rwlock_rdlock
deadlock:boost::asio
deadlock:src/xrpld/app/misc/detail/Manifest.cpp
deadlock:src/xrpld/app/misc/detail/ValidatorList.cpp
deadlock:src/xrpld/app/misc/detail/ValidatorSite.cpp
@@ -74,6 +67,11 @@ signal:src/xrpld/core/detail/Workers.cpp
signal:src/xrpld/core/JobQueue.cpp
signal:ripple::Workers::Worker
# Aggressive suppressing of deadlock tsan errors
deadlock:pthread_create
deadlock:pthread_rwlock_rdlock
deadlock:boost::asio
# Suppress SEGV crashes in TSAN itself during stringbuf operations
# This appears to be a GCC-15 TSAN instrumentation issue with basic_stringbuf::str()
# Commonly triggered in beast::Journal::ScopedStream destructor
@@ -84,11 +82,6 @@ signal:basic_ostringstream
called_from_lib:libclang_rt
race:ostreambuf_iterator
race:basic_ostream
#called_from_lib:libc++.1.dylib
#called_from_lib:libc++.abi.dylib
# Suppress SEGV in TSAN during operator new called from stringbuf
signal:operator new
# Suppress SEGV in Boost ASIO memory allocation with GCC-15 TSAN
signal:boost::asio::aligned_new
@@ -97,9 +90,6 @@ signal:boost::asio::detail::memory
# Suppress SEGV in execute_native_thread_routine
signal:execute_native_thread_routine
# Suppress nested TSAN bugs (TSAN crashing while handling a crash)
signal:nested bug in the same thread
# Suppress data race in Boost Context fiber management
# This is a false positive in Boost's exception state management during fiber context switching
race:__cxxabiv1::manage_exception_state

66
external/ubsan.supp vendored
View File

@@ -1,6 +1,5 @@
# Suppress UBSan errors in external code by source file path
# This matches any source file under the external/ directory
alignment:external
bool:external
bounds:external
@@ -70,6 +69,7 @@ vla-bound:boost
vptr_check:boost
vptr:boost
# Suppress UBSan errors in rippled code by source file path
undefined:src/libxrpl/basics/base64.cpp
undefined:src/libxrpl/basics/Number.cpp
undefined:src/libxrpl/beast/utility/beast_Journal.cpp
@@ -160,8 +160,70 @@ unsigned-integer-overflow:xrpl/nodestore/detail/varint.h
unsigned-integer-overflow:xrpl/peerfinder/detail/Counts.h
unsigned-integer-overflow:xrpl/protocol/nft.h
# Rippled intentional overflows and operations
# STAmount uses intentional negation of INT64_MIN and overflow in arithmetic
signed-integer-overflow:src/libxrpl/protocol/STAmount.cpp
unsigned-integer-overflow:src/libxrpl/protocol/STAmount.cpp
# XRPAmount test intentional overflows
signed-integer-overflow:src/test/basics/XRPAmount_test.cpp
# Peerfinder intentional overflow in counter arithmetic
unsigned-integer-overflow:src/xrpld/peerfinder/detail/Counts.h
# Signed integer overflow suppressions
signed-integer-overflow:src/test/beast/LexicalCast_test.cpp
# External library suppressions
unsigned-integer-overflow:nudb/detail/xxhash.hpp
unsigned-integer-overflow:nudb/detail/xxhash.hpp
# Protobuf intentional overflows in hash functions
# Protobuf uses intentional unsigned overflow for hash computation (stringpiece.h:393)
unsigned-integer-overflow:google/protobuf/stubs/stringpiece.h
# gRPC intentional overflows
# gRPC uses intentional overflow in timer calculations
unsigned-integer-overflow:grpc
unsigned-integer-overflow:timer_manager.cc
# Standard library intentional overflows
# These are intentional overflows in random number generation and character conversion
unsigned-integer-overflow:__random/seed_seq.h
unsigned-integer-overflow:__charconv/traits.h
# Suppress errors in RocksDB
# RocksDB uses intentional unsigned integer overflows in hash functions and CRC calculations
unsigned-integer-overflow:rocks*/b/src/util/xxhash.h
unsigned-integer-overflow:rocks*/b/src/util/xxph3.h
unsigned-integer-overflow:rocks*/b/src/util/hash.cc
unsigned-integer-overflow:rocks*/b/src/util/crc32c.cc
unsigned-integer-overflow:rocks*/b/src/util/crc32c.h
unsigned-integer-overflow:rocks*/b/src/include/rocksdb/utilities/options_type.h
unsigned-integer-overflow:rocks*/b/src/table/format.h
unsigned-integer-overflow:rocks*/b/src/table/format.cc
unsigned-integer-overflow:rocks*/b/src/table/block_based/block_based_table_builder.cc
unsigned-integer-overflow:rocks*/b/src/table/block_based/reader_common.cc
unsigned-integer-overflow:rocks*/b/src/db/version_set.cc
# RocksDB misaligned loads (intentional for performance on ARM64)
alignment:rocks*/b/src/util/crc32c_arm64.cc
# nudb intentional overflows in hash functions
unsigned-integer-overflow:nudb/detail/xxhash.hpp
alignment:nudb/detail/xxhash.hpp
# Snappy compression library intentional overflows
unsigned-integer-overflow:snapp*/b/src/snappy.cc
# Abseil intentional overflows
unsigned-integer-overflow:abse*/b/src/absl/strings/numbers.cc
unsigned-integer-overflow:abse*/b/src/absl/strings/internal/cord_rep_flat.h
# Standard library intentional overflows in chrono duration arithmetic
unsigned-integer-overflow:__chrono/duration.h
# Suppress undefined errors in RocksDB and nudb
undefined:rocks.*/b/src/util/crc32c_arm64.cc
undefined:rocks.*/b/src/util/xxhash.h
undefined:nudb