From 97086af0cb6e65f59ec6379236d06d744b4984f2 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 20 Aug 2025 11:12:06 +0200 Subject: [PATCH 01/30] Add Sanitizers documentation Signed-off-by: Uilian Ries --- examples/dev_flow.rst | 1 + .../sanitizers/compiler_sanitizers.rst | 198 ++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 examples/dev_flow/sanitizers/compiler_sanitizers.rst diff --git a/examples/dev_flow.rst b/examples/dev_flow.rst index 4363e2e079b5..21d7e0e94744 100644 --- a/examples/dev_flow.rst +++ b/examples/dev_flow.rst @@ -8,4 +8,5 @@ Developer tools and flows dev_flow/debug/step_into_dependencies dev_flow/debug/debugging_visual + dev_flow/sanitizers/compiler_sanitizers dev_flow/tool_requires/mingw diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst new file mode 100644 index 000000000000..f789417f15c3 --- /dev/null +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -0,0 +1,198 @@ +.. _examples_dev_flow_sanitizers_compiler_sanitizers: + +Compiler sanitizers +=================== + +Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, +dangling pointers, and various types of undefined behavior. + +Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. + +This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. + +Modeling and Applying Sanitizers using Settings +------------------------------------------------ + +If you want to model the sanitizer options so that the package id is affected by them, you have to +:ref:`customize new compiler sub-settings`. You should not need +modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` +instead. + +This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same +binary package with or without sanitizers, which is ideal for development and debugging workflows. + +To better illustrate this, please, first clone the sources to recreate this project. You can find them in the +`examples2 repository `_ in GitHub: + +.. code-block:: bash + + $ git clone https://github.com/conan-io/examples2.git + $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers + +In this example we are going to see how to prepare Conan to use sanitizers in different ways. + + +Configuring Sanitizers as Part of Settings +########################################## + +If you typically use a specific set of sanitizers or combinations for your builds, you can specify +them as a list of values. For example, with Clang, you might do the following: + +.. code-block:: yaml + :caption: *settings_user.yml* + :emphasize-lines: 6 + + compiler: + clang: + sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + +Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, +``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with +``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. + +It seems be a large number of options, but for Clang, these are only a portion. +To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. +The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. +For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. + +Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. + +Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. +In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. + +Adding Sanitizers as Part of the Profile +######################################## + +An option would be to add the sanitizer values as part of the profile. +This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. + +.. code-block:: ini + :caption: *~/.conan/profiles/asan* + :emphasize-lines: 6 + + include(default) + + [settings] + compiler.sanitizer=Address + + [conf] + tools.build:cflags=['-fsanitize=address'] + tools.build:cxxflags=['-fsanitize=address'] + +The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. +It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. + + +Passing the information to the compiler or build system +------------------------------------------------------- + +Here again, we have multiple choices to pass sanitizers information to the compiler or build system. + +Using from custom profiles +########################## + +It is possible to have different custom profiles defining the compiler sanitizer setting and +environment variables to inject that information to the compiler, and then passing those profiles to +Conan commands. An example of this would be a profile like: + +.. code-block:: text + :caption: *address_sanitizer_profile* + :emphasize-lines: 10,12,13,14 + + [settings] + os=Macos + os_build=Macos + arch=x86_64 + arch_build=x86_64 + compiler=apple-clang + compiler.version=10.0 + compiler.libcxx=libc++ + build_type=Release + compiler.sanitizer=Address + [env] + CFLAGS=-fsanitize=address + CXXFLAGS=-fsanitize=address + LDFLAGS=-fsanitize=address + +Then calling :command:`conan create . -pr address_sanitizer_profile` would inject +``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. + +Managing sanitizer settings with the build system +################################################# + +Another option is to make use of the information that is propagated to the *conan generator*. For +example, if we are using CMake we could use the information from the *CMakeLists.txt* to append +the flags to the compiler settings like this: + +.. code-block:: cmake + :caption: *CMakeLists.txt* + + cmake_minimum_required(VERSION 3.2) + project(SanitizerExample) + set (CMAKE_CXX_STANDARD 11) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) + if(SANITIZER) + if(SANITIZER MATCHES "(Address)") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) + endif() + endif() + add_executable(sanit_example src/main.cpp) + + +The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable +with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of +the variable. + + +Using conan Hooks to set compiler environment variables +####################################################### + +.. warning:: + + This way of adding sanitizers is recommended just for testing purposes. In general, it's not a + good practice to inject this in the environment using a Conan hook. It's much better explicitly + defining this in the profiles. + +.. important:: + + Take into account that the package ID doesn't encode information about the environment, + so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. + + +If you are not interested in modelling the settings in the Conan package you can use a +Hook to modify the environment variable and apply the sanitizer +flags to the build. It could be something like: + +.. code-block:: python + :caption: *sanitizer_hook.py* + + import os + + + class SanitizerHook(object): + def __init__(self): + self._old_cxx_flags = None + + def set_sanitize_address_flag(self): + self._old_cxx_flags = os.environ.get("CXXFLAGS") + flags_str = self._old_cxx_flags or "" + os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" + + def reset_sanitize_address_flag(self): + if self._old_cxx_flags is None: + del os.environ["CXXFLAGS"] + else: + os.environ["CXXFLAGS"] = self._old_cxx_flags + + + sanitizer = SanitizerHook() + + + def pre_build(output, conanfile, **kwargs): + sanitizer.set_sanitize_address_flag() + + + def post_build(output, conanfile, **kwargs): + sanitizer.reset_sanitize_address_flag() From 50fd020cf3a8ce44305b7fa51f50f92940bd2748 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 20 Aug 2025 11:22:31 +0200 Subject: [PATCH 02/30] Add Sanitizers Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 128 ++++-------------- 1 file changed, 24 insertions(+), 104 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index f789417f15c3..7a3fe106b92d 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -3,6 +3,12 @@ Compiler sanitizers =================== +.. warning:: + + Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime + relies on environment variables that could enable privilege escalation attacks. + Use sanitizers only in development and testing environments. + Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, dangling pointers, and various types of undefined behavior. @@ -40,7 +46,7 @@ them as a list of values. For example, with Clang, you might do the following: .. code-block:: yaml :caption: *settings_user.yml* - :emphasize-lines: 6 + :emphasize-lines: 3 compiler: clang: @@ -82,117 +88,31 @@ This way, you can easily switch between different sanitizer configurations by us The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. +Building Examples Using Sanitizers +---------------------------------- -Passing the information to the compiler or build system -------------------------------------------------------- - -Here again, we have multiple choices to pass sanitizers information to the compiler or build system. - -Using from custom profiles -########################## - -It is possible to have different custom profiles defining the compiler sanitizer setting and -environment variables to inject that information to the compiler, and then passing those profiles to -Conan commands. An example of this would be a profile like: - -.. code-block:: text - :caption: *address_sanitizer_profile* - :emphasize-lines: 10,12,13,14 - - [settings] - os=Macos - os_build=Macos - arch=x86_64 - arch_build=x86_64 - compiler=apple-clang - compiler.version=10.0 - compiler.libcxx=libc++ - build_type=Release - compiler.sanitizer=Address - [env] - CFLAGS=-fsanitize=address - CXXFLAGS=-fsanitize=address - LDFLAGS=-fsanitize=address - -Then calling :command:`conan create . -pr address_sanitizer_profile` would inject -``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. - -Managing sanitizer settings with the build system -################################################# - -Another option is to make use of the information that is propagated to the *conan generator*. For -example, if we are using CMake we could use the information from the *CMakeLists.txt* to append -the flags to the compiler settings like this: - -.. code-block:: cmake - :caption: *CMakeLists.txt* +Address Sanitizer: Index Out of Bounds +###################################### - cmake_minimum_required(VERSION 3.2) - project(SanitizerExample) - set (CMAKE_CXX_STANDARD 11) - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) - if(SANITIZER) - if(SANITIZER MATCHES "(Address)") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) - endif() - endif() - add_executable(sanit_example src/main.cpp) +**TODO** +Undefined Sanitizer: Signed Integer Overflow +############################################ -The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable -with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of -the variable. +**TODO** +Passing the information to the compiler or build system +------------------------------------------------------- -Using conan Hooks to set compiler environment variables -####################################################### - -.. warning:: - - This way of adding sanitizers is recommended just for testing purposes. In general, it's not a - good practice to inject this in the environment using a Conan hook. It's much better explicitly - defining this in the profiles. - -.. important:: - - Take into account that the package ID doesn't encode information about the environment, - so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. - - -If you are not interested in modelling the settings in the Conan package you can use a -Hook to modify the environment variable and apply the sanitizer -flags to the build. It could be something like: - -.. code-block:: python - :caption: *sanitizer_hook.py* - - import os - - - class SanitizerHook(object): - def __init__(self): - self._old_cxx_flags = None - - def set_sanitize_address_flag(self): - self._old_cxx_flags = os.environ.get("CXXFLAGS") - flags_str = self._old_cxx_flags or "" - os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" - - def reset_sanitize_address_flag(self): - if self._old_cxx_flags is None: - del os.environ["CXXFLAGS"] - else: - os.environ["CXXFLAGS"] = self._old_cxx_flags - +Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. - sanitizer = SanitizerHook() +Managing Sanitizer with CMake Toolchain +####################################### +**TODO** - def pre_build(output, conanfile, **kwargs): - sanitizer.set_sanitize_address_flag() +Mananaging Sanitizer with Conan Hooks +##################################### - def post_build(output, conanfile, **kwargs): - sanitizer.reset_sanitize_address_flag() +**TODO** \ No newline at end of file From 21c0d73a83063864af323f675401680997cee7ff Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 21 Aug 2025 09:42:11 +0200 Subject: [PATCH 03/30] Add more sections Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 140 +++++++++++++++++- 1 file changed, 136 insertions(+), 4 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 7a3fe106b92d..0c758844264a 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -74,7 +74,7 @@ This way, you can easily switch between different sanitizer configurations by us .. code-block:: ini :caption: *~/.conan/profiles/asan* - :emphasize-lines: 6 + :emphasize-lines: 7 include(default) @@ -84,22 +84,154 @@ This way, you can easily switch between different sanitizer configurations by us [conf] tools.build:cflags=['-fsanitize=address'] tools.build:cxxflags=['-fsanitize=address'] + tools.build:exelinkflags=['-fsanitize=address'] -The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. +The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. Building Examples Using Sanitizers ---------------------------------- +To show how to use sanitizers in your builds, let's consider a couple of examples. + Address Sanitizer: Index Out of Bounds ###################################### -**TODO** +In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds +index in an array, which should trigger the Address Sanitizer when running the program. + +The following code demonstrates this: + +.. code-block:: cpp + :caption: *index_out_of_bounds/main.cpp* + :emphasize-lines: 11 + + #include + #include + + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int foo[100]; + foo[100] = 42; // Out-of-bounds write + + return EXIT_SUCCESS; + } + +The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when +running the produced application. It's supported by GCC, Clang and MSVC compilers. + +To build this example, you can use Conan to invoke CMake and perform the build. + +.. code-block:: bash + + conan export index_out_of_bounds/ + conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + + +Here we are using Conan to export the recipe and build the project. +The profile file `profiles/asan` was demonstrated already and will merge with the default profile +from your configuration. The resulting build will produce an executable in a specific package folder, +in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, +then run the executable: + +.. code-block:: text + + source index_out_of_bounds/install/conanrun.sh + index_out_of_bounds + + Address sanitizer enabled + ================================================================= + ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 + WRITE of size 4 at 0x7fffbe04a6d0 thread T0 + #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) + #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 + #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 + #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) + + Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame + #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) + + This frame has 1 object(s): + [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable + HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) + SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main + +Once running the example, you should see an error message from the Address Sanitizer indicating the +out-of-bounds. The message is simplified here, but it provides useful information about the error, +including the expected index of bounds error. + Undefined Sanitizer: Signed Integer Overflow ############################################ -**TODO** +This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. +It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. +For this example, we will be using the following Conan profile: + +.. code-block:: ini + :caption: *~/.conan/profiles/asan_ubsan* + :emphasize-lines: 7 + + include(default) + + [settings] + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.build:cflags=['-fsanitize=address,undefined'] + tools.build:cxxflags=['-fsanitize=address,undefined'] + tools.build:exelinkflags=['-fsanitize=address,undefined'] + +It's important to mention it only works for GCC and Clang compilers, +as MSVC does not support the Undefined Behavior Sanitizer yet. + +The source code for this example is as follows: + +.. code-block:: cpp + :caption: *signed_integer_overflow/main.cpp* + :emphasize-lines: 12 + + #include + #include + #include + + int main(int argc, char* argv[]) { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int foo = 0x7fffffff; + foo += argc; // Signed integer overflow + + return EXIT_SUCCESS; + } + +In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. + +As next step, the code can be built using Conan and CMake, similar to the previous example: + +.. code-block:: bash + + conan export signed_integer_overflow/ + conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing + + +Once the project built successfully, you can run the example with the sanitizers enabled: + +.. code-block:: bash + + conan build signed_integer_overflow/install + ./build/signed_integer_overflow + +This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z Passing the information to the compiler or build system ------------------------------------------------------- From 91c72e4b6c7884ccfc9cb23a52791c7c2e860c1e Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 09:26:52 +0200 Subject: [PATCH 04/30] Sanitizer setting is optional Signed-off-by: Uilian Ries --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 0c758844264a..28c050f3c660 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -50,7 +50,7 @@ them as a list of values. For example, with Clang, you might do the following: compiler: clang: - sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with @@ -63,9 +63,6 @@ For MSVC, the available sanitizers are more limited, and you can find the comple Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. -Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. -In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. - Adding Sanitizers as Part of the Profile ######################################## From a8e07444ba914f15551081c3482210cf58ea0e33 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 11:54:07 +0200 Subject: [PATCH 05/30] Add toolchain and hook section Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 28c050f3c660..3fca65f5f3e1 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -84,7 +84,8 @@ This way, you can easily switch between different sanitizer configurations by us tools.build:exelinkflags=['-fsanitize=address'] The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. -It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. +It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value +as part of the compiler flags. Building Examples Using Sanitizers ---------------------------------- @@ -228,20 +229,76 @@ Once the project built successfully, you can run the example with the sanitizers conan build signed_integer_overflow/install ./build/signed_integer_overflow -This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z +This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. -Passing the information to the compiler or build system -------------------------------------------------------- +.. code-block:: text + + source signed_integer_overflow/install/conanrun.sh + signed_integer_overflow + + Address sanitizer enabled + /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' + +The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. + +Passing then Information to the Compiler or Build System +-------------------------------------------------------- Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. Managing Sanitizer with CMake Toolchain ####################################### -**TODO** +For those cases when a company or developer has a :ref:`custom CMake toolchain file ` +to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers +instead of using profiles to configure extra compiler flags. + +For example, you can create a CMake toolchain file like this: + +.. code-block:: cmake + :caption: *cmake/my_toolchain.cmake* + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + +Then, you can specify this toolchain file as part of your Conan profile as well: + +.. code-block:: ini + :caption: *profiles/asan_ubsan* + + include(default) + + [settings] + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake + +This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. + +Managing Sanitizer with Conan Hooks +################################### + +Another approach to manage sanitizers is by using :ref:`Conan hooks `. +Using hooks, you can inject compiler flags on-the-fly during the build process, +allowing for more dynamic configurations without modifying the original build files. + +For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the +``compiler.sanitizer`` setting. +.. code-block:: python + :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py -Mananaging Sanitizer with Conan Hooks -##################################### + def pre_generate(conanfile): + if conanfile.settings.get_safe("compiler.sanitizer"): + sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} + if conanfile.settings.compiler.sanitizer in sanitizer: + flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" + conanfile.conf.append("tools.build:cflags", flag) + conanfile.conf.append("tools.build:cxxflags", flag) + conanfile.conf.append("tools.build:exelinkflags", flag) -**TODO** \ No newline at end of file +The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume +the respective configuration for the compiler flags. This approach allows for more dynamic configurations +as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the +logic out for the profile management. From 99a900417f289604c78018419c65812001dc016d Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 15:04:03 +0200 Subject: [PATCH 06/30] Improve description Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 458 ++++++++++-------- 1 file changed, 255 insertions(+), 203 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 3fca65f5f3e1..14a582d6a0c0 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -1,3 +1,5 @@ +### Compiler sanitizers + .. _examples_dev_flow_sanitizers_compiler_sanitizers: Compiler sanitizers @@ -5,300 +7,350 @@ Compiler sanitizers .. warning:: - Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime - relies on environment variables that could enable privilege escalation attacks. - Use sanitizers only in development and testing environments. - -Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, -dangling pointers, and various types of undefined behavior. + Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer + runtimes rely on environment variables that could enable privilege escalation attacks. + Use sanitizers only in development and testing environments. -Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. +Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, +dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as +GCC, Clang, and MSVC support these tools through specific compiler and linker flags. -This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. +This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. -Modeling and Applying Sanitizers using Settings ------------------------------------------------- +Modeling and applying sanitizers using settings +----------------------------------------------- -If you want to model the sanitizer options so that the package id is affected by them, you have to -:ref:`customize new compiler sub-settings`. You should not need -modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` -instead. +If you want to model sanitizer options so that the package ID is affected by them, you can +:ref:`customize new compiler sub-settings `. You should not need +to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. -This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same -binary package with or without sanitizers, which is ideal for development and debugging workflows. +This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use +the same binary package with or without sanitizers. This is ideal for development and debugging workflows. -To better illustrate this, please, first clone the sources to recreate this project. You can find them in the -`examples2 repository `_ in GitHub: +To better illustrate this, please clone the sources to recreate this project. You can find them in the +`examples2 repository `_ on GitHub: .. code-block:: bash - $ git clone https://github.com/conan-io/examples2.git - $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers - -In this example we are going to see how to prepare Conan to use sanitizers in different ways. + git clone https://github.com/conan-io/examples2.git + cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers +In this example we will see how to prepare Conan to use sanitizers in different ways. -Configuring Sanitizers as Part of Settings -########################################## +Configuring sanitizers as part of settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you typically use a specific set of sanitizers or combinations for your builds, you can specify -them as a list of values. For example, with Clang, you might do the following: +a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: .. code-block:: yaml - :caption: *settings_user.yml* - :emphasize-lines: 3 + :caption: settings_user.yml + :emphasize-lines: 3 - compiler: - clang: - sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + compiler: + clang: + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] -Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, -``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with -``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. +This example defines a few common sanitizers. You can add any sanitizer your compiler supports. +The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, +``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, +``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. -It seems be a large number of options, but for Clang, these are only a portion. -To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. -The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. -For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. +It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, +refer to: -Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. +* Clang: `AddressSanitizer `_, + `ThreadSanitizer `_, + `MemorySanitizer `_, + `UndefinedBehaviorSanitizer `_. +* GCC: `Instrumentation Options `_. +* MSVC: `MSVC Sanitizers `_. -Adding Sanitizers as Part of the Profile -######################################## +**Notes on combinations**: -An option would be to add the sanitizer values as part of the profile. -This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. +* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. +* Address + UndefinedBehavior (UBSan) is a common and supported combination. +* Thread + UndefinedBehavior is also supported. +* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. -.. code-block:: ini - :caption: *~/.conan/profiles/asan* - :emphasize-lines: 7 - - include(default) +Adding sanitizers as part of the profile +---------------------------------------- - [settings] - compiler.sanitizer=Address +Another option is to add the sanitizer values as part of a profile. This way, you can easily switch between +different configurations by using dedicated profiles. - [conf] - tools.build:cflags=['-fsanitize=address'] - tools.build:cxxflags=['-fsanitize=address'] - tools.build:exelinkflags=['-fsanitize=address'] +.. code-block:: ini + :caption: compiler_sanitizers/profiles/asan -The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. -It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value -as part of the compiler flags. + include(default) -Building Examples Using Sanitizers ----------------------------------- + [settings] + build_type=Debug + compiler.sanitizer=Address -To show how to use sanitizers in your builds, let's consider a couple of examples. + [conf] + tools.build:cflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address"] + tools.build:sharedlinkflags+=["-fsanitize=address"] -Address Sanitizer: Index Out of Bounds -###################################### + [runenv] + ASAN_OPTIONS="halt_on_error=1:detect_leaks=1" -In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds -index in an array, which should trigger the Address Sanitizer when running the program. +For Visual Studio (MSVC) we can obtain an equivalent profile for AddressSanitizer: -The following code demonstrates this: +.. code-block:: ini + :caption: ~/.conan/profiles/asan -.. code-block:: cpp - :caption: *index_out_of_bounds/main.cpp* - :emphasize-lines: 11 + include(default) - #include - #include + [settings] + build_type=Debug + compiler.sanitizer=Address - int main() { - #ifdef __SANITIZE_ADDRESS__ - std::cout << "Address sanitizer enabled\n"; - #else - std::cout << "Address sanitizer not enabled\n"; - #endif + [conf] + tools.build:cxxflags+=["/fsanitize=address", "/Zi"] + tools.build:exelinkflags+=["/fsanitize=address"] - int foo[100]; - foo[100] = 42; // Out-of-bounds write +The Conan client is not capable of deducing the necessary flags from the settings and applying them automatically +during the build process. It is necessary to pass the expected sanitizer flags according to the +``compiler.sanitizer`` value as part of the compiler and linker flags. +Conan's built-in toolchains (like ``CMakeToolchain`` and ``MesonToolchain``) will automatically +pick up the flags defined in the ``[conf]`` section and apply them to the build. - return EXIT_SUCCESS; - } -The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when -running the produced application. It's supported by GCC, Clang and MSVC compilers. +Building examples using sanitizers +---------------------------------- -To build this example, you can use Conan to invoke CMake and perform the build. +To show how to use sanitizers in your builds, let's consider two examples. -.. code-block:: bash +.. note:: - conan export index_out_of_bounds/ - conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + To build your project with a sanitizer, simply use the corresponding profile. + It is crucial to **rebuild all dependencies from source** to ensure they are also instrumented, + which prevents false positives and other issues. +AddressSanitizer: index out of bounds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Here we are using Conan to export the recipe and build the project. -The profile file `profiles/asan` was demonstrated already and will merge with the default profile -from your configuration. The resulting build will produce an executable in a specific package folder, -in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, -then run the executable: +In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds index +in an array, which should trigger ASan when running the program. -.. code-block:: text +.. code-block:: cpp + :caption: index_out_of_bounds/main.cpp + :emphasize-lines: 11 - source index_out_of_bounds/install/conanrun.sh - index_out_of_bounds + #include + #include - Address sanitizer enabled - ================================================================= - ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 - WRITE of size 4 at 0x7fffbe04a6d0 thread T0 - #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) - #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 - #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 - #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif - Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame - #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) + int foo[100]; + foo[100] = 42; // Out-of-bounds write - This frame has 1 object(s): - [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable - HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork - (longjmp and C++ exceptions *are* supported) - SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main + return EXIT_SUCCESS; + } -Once running the example, you should see an error message from the Address Sanitizer indicating the -out-of-bounds. The message is simplified here, but it provides useful information about the error, -including the expected index of bounds error. +**Note:** The preprocessor check above is portable for GCC, Clang and MSVC. +The define ``__SANITIZE_ADDRESS__`` is present when ASan is active; +**To build and run this example using Conan:** -Undefined Sanitizer: Signed Integer Overflow -############################################ +.. code-block:: bash -This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. -It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. -For this example, we will be using the following Conan profile: + conan export index_out_of_bounds/ + conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + # Activate run environment to ensure sanitizer runtime and paths are set + source index_out_of_bounds/install/conanrun.sh + index_out_of_bounds -.. code-block:: ini - :caption: *~/.conan/profiles/asan_ubsan* - :emphasize-lines: 7 +**Expected output (abbreviated):** - include(default) +.. code-block:: text - [settings] - compiler.sanitizer=AddressUndefinedBehavior + Address sanitizer enabled + ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 ... + WRITE of size 4 at 0x7fffbe04a6d0 thread T0 + #0 ... in main .../index_out_of_bounds+0x12ea + ... + SUMMARY: AddressSanitizer: stack-buffer-overflow ... in main + This frame has 1 object(s): + [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable - [conf] - tools.build:cflags=['-fsanitize=address,undefined'] - tools.build:cxxflags=['-fsanitize=address,undefined'] - tools.build:exelinkflags=['-fsanitize=address,undefined'] +UndefinedBehaviorSanitizer: signed integer overflow +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It's important to mention it only works for GCC and Clang compilers, -as MSVC does not support the Undefined Behavior Sanitizer yet. +This example demonstrates how to use UBSan to detect signed integer overflow. It combines ASan and UBSan. +Create a dedicated profile: -The source code for this example is as follows: +.. code-block:: ini + :caption: ~/.conan/profiles/asan_ubsan + :emphasize-lines: 7 -.. code-block:: cpp - :caption: *signed_integer_overflow/main.cpp* - :emphasize-lines: 12 + include(default) - #include - #include - #include + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior - int main(int argc, char* argv[]) { - #ifdef __SANITIZE_ADDRESS__ - std::cout << "Address sanitizer enabled\n"; - #else - std::cout << "Address sanitizer not enabled\n"; - #endif + [conf] + tools.build:cflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address,undefined"] + tools.build:sharedlinkflags+=["-fsanitize=address,undefined"] - int foo = 0x7fffffff; - foo += argc; // Signed integer overflow +It is supported by GCC and Clang. MSVC does not support UBSan. - return EXIT_SUCCESS; - } +**Source code:** -In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. +.. code-block:: cpp + :caption: signed_integer_overflow/main.cpp + :emphasize-lines: 14 -As next step, the code can be built using Conan and CMake, similar to the previous example: + #include + #include + #include -.. code-block:: bash + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif - conan export signed_integer_overflow/ - conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing + int x = INT_MAX; + x += 42; // signed integer overflow + return EXIT_SUCCESS; + } -Once the project built successfully, you can run the example with the sanitizers enabled: +**Build and run:** .. code-block:: bash - conan build signed_integer_overflow/install - ./build/signed_integer_overflow + conan export signed_integer_overflow/ + conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing + source signed_integer_overflow/install/conanrun.sh + signed_integer_overflow -This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. +**Expected output (abbreviated):** .. code-block:: text - source signed_integer_overflow/install/conanrun.sh - signed_integer_overflow - - Address sanitizer enabled - /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' - -The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. - -Passing then Information to the Compiler or Build System --------------------------------------------------------- + Address sanitizer enabled + .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. +Passing the information to the compiler or build system +------------------------------------------------------- -Managing Sanitizer with CMake Toolchain -####################################### +Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. -For those cases when a company or developer has a :ref:`custom CMake toolchain file ` -to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers -instead of using profiles to configure extra compiler flags. +Managing sanitizers with a CMake toolchain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, you can create a CMake toolchain file like this: +If you already have a :ref:`custom CMake toolchain file ` to manage compiler +and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. .. code-block:: cmake - :caption: *cmake/my_toolchain.cmake* + :caption: cmake/my_toolchain.cmake - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + # Apply to all targets; consider per-target options for finer control + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") -Then, you can specify this toolchain file as part of your Conan profile as well: +Then, specify this toolchain file as part of your Conan profile: .. code-block:: ini - :caption: *profiles/asan_ubsan* + :caption: profiles/asan_ubsan - include(default) + include(default) - [settings] - compiler.sanitizer=AddressUndefinedBehavior + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior - [conf] - tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. -Managing Sanitizer with Conan Hooks -################################### +Managing sanitizers with Conan hooks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Another approach to manage sanitizers is by using :ref:`Conan hooks `. -Using hooks, you can inject compiler flags on-the-fly during the build process, -allowing for more dynamic configurations without modifying the original build files. +Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler +flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original +build files. -For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the -``compiler.sanitizer`` setting. +For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the +``compiler.sanitizer`` setting: .. code-block:: python - :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py - - def pre_generate(conanfile): - if conanfile.settings.get_safe("compiler.sanitizer"): - sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} - if conanfile.settings.compiler.sanitizer in sanitizer: - flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" - conanfile.conf.append("tools.build:cflags", flag) - conanfile.conf.append("tools.build:cxxflags", flag) - conanfile.conf.append("tools.build:exelinkflags", flag) - -The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume -the respective configuration for the compiler flags. This approach allows for more dynamic configurations -as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the -logic out for the profile management. + :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py + + def pre_generate(conanfile): + sani = conanfile.settings.get_safe("compiler.sanitizer") + if not sani or sani == "null": + return + mapping = { + "Address": "address", + "Leak": "leak", + "Thread": "thread", + "Memory": "memory", + "UndefinedBehavior": "undefined", + "HardwareAssistanceAddress": "hwaddress", + "KernelAddress": "kernel-address", + "AddressUndefinedBehavior": "address,undefined", + "ThreadUndefinedBehavior": "thread,undefined", + } + fs = mapping.get(sani) + if not fs: + return + flag = f"-fsanitize={fs}" + for k in ("tools.build:cflags", "tools.build:cxxflags", + "tools.build:exelinkflags", "tools.build:sharedlinkflags"): + conanfile.conf.append(k, flag) + # Optional: better stack traces + conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") + +The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final +configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity +as it moves logic out of profile management. + +Additional recommendations +-------------------------- + +* Debug info and optimization: + + * For ASan/TSan, ``-O1`` or ``-O2`` generally works; for MSan, prefer ``-O1`` and avoid aggressive inlining. + * ``-fno-omit-frame-pointer`` helps stack traces. + +* Runtime symbolization: + + * Useful settings for CI: + + * ``ASAN_OPTIONS=halt_on_error=1:detect_leaks=1:log_path=asan``. + * ``UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:log_path=ubsan``. + +* Suppressions: + + * For ASan: ``ASAN_OPTIONS=suppressions=asan.supp``. + * For UBSan: ``UBSAN_OPTIONS=suppressions=ubsan.supp``. + * Keep suppressions under version control and load them in CI jobs. + +* Third-party dependencies: + + * Mixed instrumented/uninstrumented code can lead to false positives or crashes, especially with MSan. + * Prefer building dependencies with the same sanitizer or limit sanitizers to leaf applications. + +* MSVC and Windows notes: + + * ASan with MSVC/Clang-cl uses ``/fsanitize=address`` and PDBs via ``/Zi``. Not supported for 32-bit targets. + * KAsan requires Windows 11. + * Some features are limited when using whole program optimization (``/GL``) or certain runtime libraries. From a4ab90f7bfdb52ad6fcd756ba6da995b9936845a Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 12:49:19 +0200 Subject: [PATCH 07/30] Remove unsed header. Co-authored-by: Carlos Zoido --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 14a582d6a0c0..c1e4513feefb 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -1,5 +1,3 @@ -### Compiler sanitizers - .. _examples_dev_flow_sanitizers_compiler_sanitizers: Compiler sanitizers From 56355441295fda384eef367845d21e345e092d13 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 13:49:15 +0200 Subject: [PATCH 08/30] Update sanitizers warning --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index c1e4513feefb..5aca1a985a3a 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -5,7 +5,9 @@ Compiler sanitizers .. warning:: - Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer + Using sanitizers in production, especially with programs that run with elevated privileges (for example, SUID binaries on Linux), is dangerous. + The sanitizer runtime libraries depend on environment variables, which could allow privilege escalation attacks. + Use sanitizers only in development and testing environments. runtimes rely on environment variables that could enable privilege escalation attacks. Use sanitizers only in development and testing environments. From ab0bacc7ef773c629c6ea91b257d0d87a3eea63a Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 13:50:13 +0200 Subject: [PATCH 09/30] Improve document description Co-authored-by: Carlos Zoido --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 5aca1a985a3a..45afba9d54e0 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -15,7 +15,7 @@ Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as GCC, Clang, and MSVC support these tools through specific compiler and linker flags. -This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. +This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. Modeling and applying sanitizers using settings ----------------------------------------------- From 000fed7004fc69ef1914cae6f40beb6aaf9803d5 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 08:10:00 +0200 Subject: [PATCH 10/30] Remove Sanitizers with Conan hooks section Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 45afba9d54e0..0bdc8a9dbc75 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -281,48 +281,6 @@ Then, specify this toolchain file as part of your Conan profile: This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. -Managing sanitizers with Conan hooks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler -flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original -build files. - -For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the -``compiler.sanitizer`` setting: - -.. code-block:: python - :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py - - def pre_generate(conanfile): - sani = conanfile.settings.get_safe("compiler.sanitizer") - if not sani or sani == "null": - return - mapping = { - "Address": "address", - "Leak": "leak", - "Thread": "thread", - "Memory": "memory", - "UndefinedBehavior": "undefined", - "HardwareAssistanceAddress": "hwaddress", - "KernelAddress": "kernel-address", - "AddressUndefinedBehavior": "address,undefined", - "ThreadUndefinedBehavior": "thread,undefined", - } - fs = mapping.get(sani) - if not fs: - return - flag = f"-fsanitize={fs}" - for k in ("tools.build:cflags", "tools.build:cxxflags", - "tools.build:exelinkflags", "tools.build:sharedlinkflags"): - conanfile.conf.append(k, flag) - # Optional: better stack traces - conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") - -The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final -configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity -as it moves logic out of profile management. - Additional recommendations -------------------------- From 287a6d0328d02a707ee0d4d2950dcf288d77bfd5 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 20 Aug 2025 11:12:06 +0200 Subject: [PATCH 11/30] Add Sanitizers documentation Signed-off-by: Uilian Ries --- examples/dev_flow.rst | 1 + .../sanitizers/compiler_sanitizers.rst | 198 ++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 examples/dev_flow/sanitizers/compiler_sanitizers.rst diff --git a/examples/dev_flow.rst b/examples/dev_flow.rst index 4363e2e079b5..21d7e0e94744 100644 --- a/examples/dev_flow.rst +++ b/examples/dev_flow.rst @@ -8,4 +8,5 @@ Developer tools and flows dev_flow/debug/step_into_dependencies dev_flow/debug/debugging_visual + dev_flow/sanitizers/compiler_sanitizers dev_flow/tool_requires/mingw diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst new file mode 100644 index 000000000000..f789417f15c3 --- /dev/null +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -0,0 +1,198 @@ +.. _examples_dev_flow_sanitizers_compiler_sanitizers: + +Compiler sanitizers +=================== + +Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, +dangling pointers, and various types of undefined behavior. + +Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. + +This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. + +Modeling and Applying Sanitizers using Settings +------------------------------------------------ + +If you want to model the sanitizer options so that the package id is affected by them, you have to +:ref:`customize new compiler sub-settings`. You should not need +modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` +instead. + +This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same +binary package with or without sanitizers, which is ideal for development and debugging workflows. + +To better illustrate this, please, first clone the sources to recreate this project. You can find them in the +`examples2 repository `_ in GitHub: + +.. code-block:: bash + + $ git clone https://github.com/conan-io/examples2.git + $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers + +In this example we are going to see how to prepare Conan to use sanitizers in different ways. + + +Configuring Sanitizers as Part of Settings +########################################## + +If you typically use a specific set of sanitizers or combinations for your builds, you can specify +them as a list of values. For example, with Clang, you might do the following: + +.. code-block:: yaml + :caption: *settings_user.yml* + :emphasize-lines: 6 + + compiler: + clang: + sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + +Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, +``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with +``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. + +It seems be a large number of options, but for Clang, these are only a portion. +To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. +The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. +For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. + +Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. + +Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. +In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. + +Adding Sanitizers as Part of the Profile +######################################## + +An option would be to add the sanitizer values as part of the profile. +This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. + +.. code-block:: ini + :caption: *~/.conan/profiles/asan* + :emphasize-lines: 6 + + include(default) + + [settings] + compiler.sanitizer=Address + + [conf] + tools.build:cflags=['-fsanitize=address'] + tools.build:cxxflags=['-fsanitize=address'] + +The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. +It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. + + +Passing the information to the compiler or build system +------------------------------------------------------- + +Here again, we have multiple choices to pass sanitizers information to the compiler or build system. + +Using from custom profiles +########################## + +It is possible to have different custom profiles defining the compiler sanitizer setting and +environment variables to inject that information to the compiler, and then passing those profiles to +Conan commands. An example of this would be a profile like: + +.. code-block:: text + :caption: *address_sanitizer_profile* + :emphasize-lines: 10,12,13,14 + + [settings] + os=Macos + os_build=Macos + arch=x86_64 + arch_build=x86_64 + compiler=apple-clang + compiler.version=10.0 + compiler.libcxx=libc++ + build_type=Release + compiler.sanitizer=Address + [env] + CFLAGS=-fsanitize=address + CXXFLAGS=-fsanitize=address + LDFLAGS=-fsanitize=address + +Then calling :command:`conan create . -pr address_sanitizer_profile` would inject +``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. + +Managing sanitizer settings with the build system +################################################# + +Another option is to make use of the information that is propagated to the *conan generator*. For +example, if we are using CMake we could use the information from the *CMakeLists.txt* to append +the flags to the compiler settings like this: + +.. code-block:: cmake + :caption: *CMakeLists.txt* + + cmake_minimum_required(VERSION 3.2) + project(SanitizerExample) + set (CMAKE_CXX_STANDARD 11) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) + if(SANITIZER) + if(SANITIZER MATCHES "(Address)") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) + endif() + endif() + add_executable(sanit_example src/main.cpp) + + +The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable +with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of +the variable. + + +Using conan Hooks to set compiler environment variables +####################################################### + +.. warning:: + + This way of adding sanitizers is recommended just for testing purposes. In general, it's not a + good practice to inject this in the environment using a Conan hook. It's much better explicitly + defining this in the profiles. + +.. important:: + + Take into account that the package ID doesn't encode information about the environment, + so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. + + +If you are not interested in modelling the settings in the Conan package you can use a +Hook to modify the environment variable and apply the sanitizer +flags to the build. It could be something like: + +.. code-block:: python + :caption: *sanitizer_hook.py* + + import os + + + class SanitizerHook(object): + def __init__(self): + self._old_cxx_flags = None + + def set_sanitize_address_flag(self): + self._old_cxx_flags = os.environ.get("CXXFLAGS") + flags_str = self._old_cxx_flags or "" + os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" + + def reset_sanitize_address_flag(self): + if self._old_cxx_flags is None: + del os.environ["CXXFLAGS"] + else: + os.environ["CXXFLAGS"] = self._old_cxx_flags + + + sanitizer = SanitizerHook() + + + def pre_build(output, conanfile, **kwargs): + sanitizer.set_sanitize_address_flag() + + + def post_build(output, conanfile, **kwargs): + sanitizer.reset_sanitize_address_flag() From 2b1d233f77d50a8c19ea42be61bdd67643bc91b5 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 20 Aug 2025 11:22:31 +0200 Subject: [PATCH 12/30] Add Sanitizers Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 128 ++++-------------- 1 file changed, 24 insertions(+), 104 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index f789417f15c3..7a3fe106b92d 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -3,6 +3,12 @@ Compiler sanitizers =================== +.. warning:: + + Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime + relies on environment variables that could enable privilege escalation attacks. + Use sanitizers only in development and testing environments. + Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, dangling pointers, and various types of undefined behavior. @@ -40,7 +46,7 @@ them as a list of values. For example, with Clang, you might do the following: .. code-block:: yaml :caption: *settings_user.yml* - :emphasize-lines: 6 + :emphasize-lines: 3 compiler: clang: @@ -82,117 +88,31 @@ This way, you can easily switch between different sanitizer configurations by us The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. +Building Examples Using Sanitizers +---------------------------------- -Passing the information to the compiler or build system -------------------------------------------------------- - -Here again, we have multiple choices to pass sanitizers information to the compiler or build system. - -Using from custom profiles -########################## - -It is possible to have different custom profiles defining the compiler sanitizer setting and -environment variables to inject that information to the compiler, and then passing those profiles to -Conan commands. An example of this would be a profile like: - -.. code-block:: text - :caption: *address_sanitizer_profile* - :emphasize-lines: 10,12,13,14 - - [settings] - os=Macos - os_build=Macos - arch=x86_64 - arch_build=x86_64 - compiler=apple-clang - compiler.version=10.0 - compiler.libcxx=libc++ - build_type=Release - compiler.sanitizer=Address - [env] - CFLAGS=-fsanitize=address - CXXFLAGS=-fsanitize=address - LDFLAGS=-fsanitize=address - -Then calling :command:`conan create . -pr address_sanitizer_profile` would inject -``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. - -Managing sanitizer settings with the build system -################################################# - -Another option is to make use of the information that is propagated to the *conan generator*. For -example, if we are using CMake we could use the information from the *CMakeLists.txt* to append -the flags to the compiler settings like this: - -.. code-block:: cmake - :caption: *CMakeLists.txt* +Address Sanitizer: Index Out of Bounds +###################################### - cmake_minimum_required(VERSION 3.2) - project(SanitizerExample) - set (CMAKE_CXX_STANDARD 11) - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) - if(SANITIZER) - if(SANITIZER MATCHES "(Address)") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) - endif() - endif() - add_executable(sanit_example src/main.cpp) +**TODO** +Undefined Sanitizer: Signed Integer Overflow +############################################ -The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable -with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of -the variable. +**TODO** +Passing the information to the compiler or build system +------------------------------------------------------- -Using conan Hooks to set compiler environment variables -####################################################### - -.. warning:: - - This way of adding sanitizers is recommended just for testing purposes. In general, it's not a - good practice to inject this in the environment using a Conan hook. It's much better explicitly - defining this in the profiles. - -.. important:: - - Take into account that the package ID doesn't encode information about the environment, - so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. - - -If you are not interested in modelling the settings in the Conan package you can use a -Hook to modify the environment variable and apply the sanitizer -flags to the build. It could be something like: - -.. code-block:: python - :caption: *sanitizer_hook.py* - - import os - - - class SanitizerHook(object): - def __init__(self): - self._old_cxx_flags = None - - def set_sanitize_address_flag(self): - self._old_cxx_flags = os.environ.get("CXXFLAGS") - flags_str = self._old_cxx_flags or "" - os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" - - def reset_sanitize_address_flag(self): - if self._old_cxx_flags is None: - del os.environ["CXXFLAGS"] - else: - os.environ["CXXFLAGS"] = self._old_cxx_flags - +Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. - sanitizer = SanitizerHook() +Managing Sanitizer with CMake Toolchain +####################################### +**TODO** - def pre_build(output, conanfile, **kwargs): - sanitizer.set_sanitize_address_flag() +Mananaging Sanitizer with Conan Hooks +##################################### - def post_build(output, conanfile, **kwargs): - sanitizer.reset_sanitize_address_flag() +**TODO** \ No newline at end of file From e016d2f3798852f9892f6e56a9e4a237d5fe3203 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 21 Aug 2025 09:42:11 +0200 Subject: [PATCH 13/30] Add more sections Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 140 +++++++++++++++++- 1 file changed, 136 insertions(+), 4 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 7a3fe106b92d..0c758844264a 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -74,7 +74,7 @@ This way, you can easily switch between different sanitizer configurations by us .. code-block:: ini :caption: *~/.conan/profiles/asan* - :emphasize-lines: 6 + :emphasize-lines: 7 include(default) @@ -84,22 +84,154 @@ This way, you can easily switch between different sanitizer configurations by us [conf] tools.build:cflags=['-fsanitize=address'] tools.build:cxxflags=['-fsanitize=address'] + tools.build:exelinkflags=['-fsanitize=address'] -The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. +The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. Building Examples Using Sanitizers ---------------------------------- +To show how to use sanitizers in your builds, let's consider a couple of examples. + Address Sanitizer: Index Out of Bounds ###################################### -**TODO** +In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds +index in an array, which should trigger the Address Sanitizer when running the program. + +The following code demonstrates this: + +.. code-block:: cpp + :caption: *index_out_of_bounds/main.cpp* + :emphasize-lines: 11 + + #include + #include + + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int foo[100]; + foo[100] = 42; // Out-of-bounds write + + return EXIT_SUCCESS; + } + +The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when +running the produced application. It's supported by GCC, Clang and MSVC compilers. + +To build this example, you can use Conan to invoke CMake and perform the build. + +.. code-block:: bash + + conan export index_out_of_bounds/ + conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + + +Here we are using Conan to export the recipe and build the project. +The profile file `profiles/asan` was demonstrated already and will merge with the default profile +from your configuration. The resulting build will produce an executable in a specific package folder, +in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, +then run the executable: + +.. code-block:: text + + source index_out_of_bounds/install/conanrun.sh + index_out_of_bounds + + Address sanitizer enabled + ================================================================= + ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 + WRITE of size 4 at 0x7fffbe04a6d0 thread T0 + #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) + #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 + #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 + #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) + + Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame + #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) + + This frame has 1 object(s): + [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable + HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) + SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main + +Once running the example, you should see an error message from the Address Sanitizer indicating the +out-of-bounds. The message is simplified here, but it provides useful information about the error, +including the expected index of bounds error. + Undefined Sanitizer: Signed Integer Overflow ############################################ -**TODO** +This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. +It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. +For this example, we will be using the following Conan profile: + +.. code-block:: ini + :caption: *~/.conan/profiles/asan_ubsan* + :emphasize-lines: 7 + + include(default) + + [settings] + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.build:cflags=['-fsanitize=address,undefined'] + tools.build:cxxflags=['-fsanitize=address,undefined'] + tools.build:exelinkflags=['-fsanitize=address,undefined'] + +It's important to mention it only works for GCC and Clang compilers, +as MSVC does not support the Undefined Behavior Sanitizer yet. + +The source code for this example is as follows: + +.. code-block:: cpp + :caption: *signed_integer_overflow/main.cpp* + :emphasize-lines: 12 + + #include + #include + #include + + int main(int argc, char* argv[]) { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int foo = 0x7fffffff; + foo += argc; // Signed integer overflow + + return EXIT_SUCCESS; + } + +In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. + +As next step, the code can be built using Conan and CMake, similar to the previous example: + +.. code-block:: bash + + conan export signed_integer_overflow/ + conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing + + +Once the project built successfully, you can run the example with the sanitizers enabled: + +.. code-block:: bash + + conan build signed_integer_overflow/install + ./build/signed_integer_overflow + +This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z Passing the information to the compiler or build system ------------------------------------------------------- From 1e6e16d3ebc33288a9c1c38871f3512279a47052 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 09:26:52 +0200 Subject: [PATCH 14/30] Sanitizer setting is optional Signed-off-by: Uilian Ries --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 0c758844264a..28c050f3c660 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -50,7 +50,7 @@ them as a list of values. For example, with Clang, you might do the following: compiler: clang: - sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with @@ -63,9 +63,6 @@ For MSVC, the available sanitizers are more limited, and you can find the comple Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. -Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. -In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. - Adding Sanitizers as Part of the Profile ######################################## From 277548ede2d5d9415f34c1238caf690831ea9169 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 11:54:07 +0200 Subject: [PATCH 15/30] Add toolchain and hook section Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 28c050f3c660..3fca65f5f3e1 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -84,7 +84,8 @@ This way, you can easily switch between different sanitizer configurations by us tools.build:exelinkflags=['-fsanitize=address'] The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. -It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. +It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value +as part of the compiler flags. Building Examples Using Sanitizers ---------------------------------- @@ -228,20 +229,76 @@ Once the project built successfully, you can run the example with the sanitizers conan build signed_integer_overflow/install ./build/signed_integer_overflow -This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z +This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. -Passing the information to the compiler or build system -------------------------------------------------------- +.. code-block:: text + + source signed_integer_overflow/install/conanrun.sh + signed_integer_overflow + + Address sanitizer enabled + /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' + +The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. + +Passing then Information to the Compiler or Build System +-------------------------------------------------------- Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. Managing Sanitizer with CMake Toolchain ####################################### -**TODO** +For those cases when a company or developer has a :ref:`custom CMake toolchain file ` +to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers +instead of using profiles to configure extra compiler flags. + +For example, you can create a CMake toolchain file like this: + +.. code-block:: cmake + :caption: *cmake/my_toolchain.cmake* + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + +Then, you can specify this toolchain file as part of your Conan profile as well: + +.. code-block:: ini + :caption: *profiles/asan_ubsan* + + include(default) + + [settings] + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake + +This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. + +Managing Sanitizer with Conan Hooks +################################### + +Another approach to manage sanitizers is by using :ref:`Conan hooks `. +Using hooks, you can inject compiler flags on-the-fly during the build process, +allowing for more dynamic configurations without modifying the original build files. + +For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the +``compiler.sanitizer`` setting. +.. code-block:: python + :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py -Mananaging Sanitizer with Conan Hooks -##################################### + def pre_generate(conanfile): + if conanfile.settings.get_safe("compiler.sanitizer"): + sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} + if conanfile.settings.compiler.sanitizer in sanitizer: + flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" + conanfile.conf.append("tools.build:cflags", flag) + conanfile.conf.append("tools.build:cxxflags", flag) + conanfile.conf.append("tools.build:exelinkflags", flag) -**TODO** \ No newline at end of file +The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume +the respective configuration for the compiler flags. This approach allows for more dynamic configurations +as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the +logic out for the profile management. From 370259ce6ab3a44b934a2490bce263bfbd7430b9 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 22 Aug 2025 15:04:03 +0200 Subject: [PATCH 16/30] Improve description Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 458 ++++++++++-------- 1 file changed, 255 insertions(+), 203 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 3fca65f5f3e1..14a582d6a0c0 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -1,3 +1,5 @@ +### Compiler sanitizers + .. _examples_dev_flow_sanitizers_compiler_sanitizers: Compiler sanitizers @@ -5,300 +7,350 @@ Compiler sanitizers .. warning:: - Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime - relies on environment variables that could enable privilege escalation attacks. - Use sanitizers only in development and testing environments. - -Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, -dangling pointers, and various types of undefined behavior. + Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer + runtimes rely on environment variables that could enable privilege escalation attacks. + Use sanitizers only in development and testing environments. -Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. +Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, +dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as +GCC, Clang, and MSVC support these tools through specific compiler and linker flags. -This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. +This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. -Modeling and Applying Sanitizers using Settings ------------------------------------------------- +Modeling and applying sanitizers using settings +----------------------------------------------- -If you want to model the sanitizer options so that the package id is affected by them, you have to -:ref:`customize new compiler sub-settings`. You should not need -modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` -instead. +If you want to model sanitizer options so that the package ID is affected by them, you can +:ref:`customize new compiler sub-settings `. You should not need +to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. -This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same -binary package with or without sanitizers, which is ideal for development and debugging workflows. +This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use +the same binary package with or without sanitizers. This is ideal for development and debugging workflows. -To better illustrate this, please, first clone the sources to recreate this project. You can find them in the -`examples2 repository `_ in GitHub: +To better illustrate this, please clone the sources to recreate this project. You can find them in the +`examples2 repository `_ on GitHub: .. code-block:: bash - $ git clone https://github.com/conan-io/examples2.git - $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers - -In this example we are going to see how to prepare Conan to use sanitizers in different ways. + git clone https://github.com/conan-io/examples2.git + cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers +In this example we will see how to prepare Conan to use sanitizers in different ways. -Configuring Sanitizers as Part of Settings -########################################## +Configuring sanitizers as part of settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you typically use a specific set of sanitizers or combinations for your builds, you can specify -them as a list of values. For example, with Clang, you might do the following: +a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: .. code-block:: yaml - :caption: *settings_user.yml* - :emphasize-lines: 3 + :caption: settings_user.yml + :emphasize-lines: 3 - compiler: - clang: - sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + compiler: + clang: + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] -Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, -``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with -``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. +This example defines a few common sanitizers. You can add any sanitizer your compiler supports. +The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, +``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, +``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. -It seems be a large number of options, but for Clang, these are only a portion. -To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. -The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. -For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. +It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, +refer to: -Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. +* Clang: `AddressSanitizer `_, + `ThreadSanitizer `_, + `MemorySanitizer `_, + `UndefinedBehaviorSanitizer `_. +* GCC: `Instrumentation Options `_. +* MSVC: `MSVC Sanitizers `_. -Adding Sanitizers as Part of the Profile -######################################## +**Notes on combinations**: -An option would be to add the sanitizer values as part of the profile. -This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. +* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. +* Address + UndefinedBehavior (UBSan) is a common and supported combination. +* Thread + UndefinedBehavior is also supported. +* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. -.. code-block:: ini - :caption: *~/.conan/profiles/asan* - :emphasize-lines: 7 - - include(default) +Adding sanitizers as part of the profile +---------------------------------------- - [settings] - compiler.sanitizer=Address +Another option is to add the sanitizer values as part of a profile. This way, you can easily switch between +different configurations by using dedicated profiles. - [conf] - tools.build:cflags=['-fsanitize=address'] - tools.build:cxxflags=['-fsanitize=address'] - tools.build:exelinkflags=['-fsanitize=address'] +.. code-block:: ini + :caption: compiler_sanitizers/profiles/asan -The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. -It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value -as part of the compiler flags. + include(default) -Building Examples Using Sanitizers ----------------------------------- + [settings] + build_type=Debug + compiler.sanitizer=Address -To show how to use sanitizers in your builds, let's consider a couple of examples. + [conf] + tools.build:cflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address"] + tools.build:sharedlinkflags+=["-fsanitize=address"] -Address Sanitizer: Index Out of Bounds -###################################### + [runenv] + ASAN_OPTIONS="halt_on_error=1:detect_leaks=1" -In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds -index in an array, which should trigger the Address Sanitizer when running the program. +For Visual Studio (MSVC) we can obtain an equivalent profile for AddressSanitizer: -The following code demonstrates this: +.. code-block:: ini + :caption: ~/.conan/profiles/asan -.. code-block:: cpp - :caption: *index_out_of_bounds/main.cpp* - :emphasize-lines: 11 + include(default) - #include - #include + [settings] + build_type=Debug + compiler.sanitizer=Address - int main() { - #ifdef __SANITIZE_ADDRESS__ - std::cout << "Address sanitizer enabled\n"; - #else - std::cout << "Address sanitizer not enabled\n"; - #endif + [conf] + tools.build:cxxflags+=["/fsanitize=address", "/Zi"] + tools.build:exelinkflags+=["/fsanitize=address"] - int foo[100]; - foo[100] = 42; // Out-of-bounds write +The Conan client is not capable of deducing the necessary flags from the settings and applying them automatically +during the build process. It is necessary to pass the expected sanitizer flags according to the +``compiler.sanitizer`` value as part of the compiler and linker flags. +Conan's built-in toolchains (like ``CMakeToolchain`` and ``MesonToolchain``) will automatically +pick up the flags defined in the ``[conf]`` section and apply them to the build. - return EXIT_SUCCESS; - } -The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when -running the produced application. It's supported by GCC, Clang and MSVC compilers. +Building examples using sanitizers +---------------------------------- -To build this example, you can use Conan to invoke CMake and perform the build. +To show how to use sanitizers in your builds, let's consider two examples. -.. code-block:: bash +.. note:: - conan export index_out_of_bounds/ - conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + To build your project with a sanitizer, simply use the corresponding profile. + It is crucial to **rebuild all dependencies from source** to ensure they are also instrumented, + which prevents false positives and other issues. +AddressSanitizer: index out of bounds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Here we are using Conan to export the recipe and build the project. -The profile file `profiles/asan` was demonstrated already and will merge with the default profile -from your configuration. The resulting build will produce an executable in a specific package folder, -in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, -then run the executable: +In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds index +in an array, which should trigger ASan when running the program. -.. code-block:: text +.. code-block:: cpp + :caption: index_out_of_bounds/main.cpp + :emphasize-lines: 11 - source index_out_of_bounds/install/conanrun.sh - index_out_of_bounds + #include + #include - Address sanitizer enabled - ================================================================= - ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 - WRITE of size 4 at 0x7fffbe04a6d0 thread T0 - #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) - #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 - #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 - #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif - Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame - #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) + int foo[100]; + foo[100] = 42; // Out-of-bounds write - This frame has 1 object(s): - [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable - HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork - (longjmp and C++ exceptions *are* supported) - SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main + return EXIT_SUCCESS; + } -Once running the example, you should see an error message from the Address Sanitizer indicating the -out-of-bounds. The message is simplified here, but it provides useful information about the error, -including the expected index of bounds error. +**Note:** The preprocessor check above is portable for GCC, Clang and MSVC. +The define ``__SANITIZE_ADDRESS__`` is present when ASan is active; +**To build and run this example using Conan:** -Undefined Sanitizer: Signed Integer Overflow -############################################ +.. code-block:: bash -This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. -It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. -For this example, we will be using the following Conan profile: + conan export index_out_of_bounds/ + conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + # Activate run environment to ensure sanitizer runtime and paths are set + source index_out_of_bounds/install/conanrun.sh + index_out_of_bounds -.. code-block:: ini - :caption: *~/.conan/profiles/asan_ubsan* - :emphasize-lines: 7 +**Expected output (abbreviated):** - include(default) +.. code-block:: text - [settings] - compiler.sanitizer=AddressUndefinedBehavior + Address sanitizer enabled + ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 ... + WRITE of size 4 at 0x7fffbe04a6d0 thread T0 + #0 ... in main .../index_out_of_bounds+0x12ea + ... + SUMMARY: AddressSanitizer: stack-buffer-overflow ... in main + This frame has 1 object(s): + [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable - [conf] - tools.build:cflags=['-fsanitize=address,undefined'] - tools.build:cxxflags=['-fsanitize=address,undefined'] - tools.build:exelinkflags=['-fsanitize=address,undefined'] +UndefinedBehaviorSanitizer: signed integer overflow +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -It's important to mention it only works for GCC and Clang compilers, -as MSVC does not support the Undefined Behavior Sanitizer yet. +This example demonstrates how to use UBSan to detect signed integer overflow. It combines ASan and UBSan. +Create a dedicated profile: -The source code for this example is as follows: +.. code-block:: ini + :caption: ~/.conan/profiles/asan_ubsan + :emphasize-lines: 7 -.. code-block:: cpp - :caption: *signed_integer_overflow/main.cpp* - :emphasize-lines: 12 + include(default) - #include - #include - #include + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior - int main(int argc, char* argv[]) { - #ifdef __SANITIZE_ADDRESS__ - std::cout << "Address sanitizer enabled\n"; - #else - std::cout << "Address sanitizer not enabled\n"; - #endif + [conf] + tools.build:cflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address,undefined"] + tools.build:sharedlinkflags+=["-fsanitize=address,undefined"] - int foo = 0x7fffffff; - foo += argc; // Signed integer overflow +It is supported by GCC and Clang. MSVC does not support UBSan. - return EXIT_SUCCESS; - } +**Source code:** -In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. +.. code-block:: cpp + :caption: signed_integer_overflow/main.cpp + :emphasize-lines: 14 -As next step, the code can be built using Conan and CMake, similar to the previous example: + #include + #include + #include -.. code-block:: bash + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif - conan export signed_integer_overflow/ - conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing + int x = INT_MAX; + x += 42; // signed integer overflow + return EXIT_SUCCESS; + } -Once the project built successfully, you can run the example with the sanitizers enabled: +**Build and run:** .. code-block:: bash - conan build signed_integer_overflow/install - ./build/signed_integer_overflow + conan export signed_integer_overflow/ + conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing + source signed_integer_overflow/install/conanrun.sh + signed_integer_overflow -This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. +**Expected output (abbreviated):** .. code-block:: text - source signed_integer_overflow/install/conanrun.sh - signed_integer_overflow - - Address sanitizer enabled - /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' - -The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. - -Passing then Information to the Compiler or Build System --------------------------------------------------------- + Address sanitizer enabled + .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. +Passing the information to the compiler or build system +------------------------------------------------------- -Managing Sanitizer with CMake Toolchain -####################################### +Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. -For those cases when a company or developer has a :ref:`custom CMake toolchain file ` -to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers -instead of using profiles to configure extra compiler flags. +Managing sanitizers with a CMake toolchain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, you can create a CMake toolchain file like this: +If you already have a :ref:`custom CMake toolchain file ` to manage compiler +and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. .. code-block:: cmake - :caption: *cmake/my_toolchain.cmake* + :caption: cmake/my_toolchain.cmake - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + # Apply to all targets; consider per-target options for finer control + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") -Then, you can specify this toolchain file as part of your Conan profile as well: +Then, specify this toolchain file as part of your Conan profile: .. code-block:: ini - :caption: *profiles/asan_ubsan* + :caption: profiles/asan_ubsan - include(default) + include(default) - [settings] - compiler.sanitizer=AddressUndefinedBehavior + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior - [conf] - tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. -Managing Sanitizer with Conan Hooks -################################### +Managing sanitizers with Conan hooks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Another approach to manage sanitizers is by using :ref:`Conan hooks `. -Using hooks, you can inject compiler flags on-the-fly during the build process, -allowing for more dynamic configurations without modifying the original build files. +Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler +flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original +build files. -For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the -``compiler.sanitizer`` setting. +For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the +``compiler.sanitizer`` setting: .. code-block:: python - :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py - - def pre_generate(conanfile): - if conanfile.settings.get_safe("compiler.sanitizer"): - sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} - if conanfile.settings.compiler.sanitizer in sanitizer: - flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" - conanfile.conf.append("tools.build:cflags", flag) - conanfile.conf.append("tools.build:cxxflags", flag) - conanfile.conf.append("tools.build:exelinkflags", flag) - -The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume -the respective configuration for the compiler flags. This approach allows for more dynamic configurations -as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the -logic out for the profile management. + :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py + + def pre_generate(conanfile): + sani = conanfile.settings.get_safe("compiler.sanitizer") + if not sani or sani == "null": + return + mapping = { + "Address": "address", + "Leak": "leak", + "Thread": "thread", + "Memory": "memory", + "UndefinedBehavior": "undefined", + "HardwareAssistanceAddress": "hwaddress", + "KernelAddress": "kernel-address", + "AddressUndefinedBehavior": "address,undefined", + "ThreadUndefinedBehavior": "thread,undefined", + } + fs = mapping.get(sani) + if not fs: + return + flag = f"-fsanitize={fs}" + for k in ("tools.build:cflags", "tools.build:cxxflags", + "tools.build:exelinkflags", "tools.build:sharedlinkflags"): + conanfile.conf.append(k, flag) + # Optional: better stack traces + conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") + +The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final +configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity +as it moves logic out of profile management. + +Additional recommendations +-------------------------- + +* Debug info and optimization: + + * For ASan/TSan, ``-O1`` or ``-O2`` generally works; for MSan, prefer ``-O1`` and avoid aggressive inlining. + * ``-fno-omit-frame-pointer`` helps stack traces. + +* Runtime symbolization: + + * Useful settings for CI: + + * ``ASAN_OPTIONS=halt_on_error=1:detect_leaks=1:log_path=asan``. + * ``UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:log_path=ubsan``. + +* Suppressions: + + * For ASan: ``ASAN_OPTIONS=suppressions=asan.supp``. + * For UBSan: ``UBSAN_OPTIONS=suppressions=ubsan.supp``. + * Keep suppressions under version control and load them in CI jobs. + +* Third-party dependencies: + + * Mixed instrumented/uninstrumented code can lead to false positives or crashes, especially with MSan. + * Prefer building dependencies with the same sanitizer or limit sanitizers to leaf applications. + +* MSVC and Windows notes: + + * ASan with MSVC/Clang-cl uses ``/fsanitize=address`` and PDBs via ``/Zi``. Not supported for 32-bit targets. + * KAsan requires Windows 11. + * Some features are limited when using whole program optimization (``/GL``) or certain runtime libraries. From a056050b23023d5d07dbcb24eba81ca68aef0ecf Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 12:49:19 +0200 Subject: [PATCH 17/30] Remove unsed header. Co-authored-by: Carlos Zoido --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 14a582d6a0c0..c1e4513feefb 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -1,5 +1,3 @@ -### Compiler sanitizers - .. _examples_dev_flow_sanitizers_compiler_sanitizers: Compiler sanitizers From 3502b82856cf8fa643c6b69699e555fdb0c6cc33 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 13:49:15 +0200 Subject: [PATCH 18/30] Update sanitizers warning --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index c1e4513feefb..5aca1a985a3a 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -5,7 +5,9 @@ Compiler sanitizers .. warning:: - Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer + Using sanitizers in production, especially with programs that run with elevated privileges (for example, SUID binaries on Linux), is dangerous. + The sanitizer runtime libraries depend on environment variables, which could allow privilege escalation attacks. + Use sanitizers only in development and testing environments. runtimes rely on environment variables that could enable privilege escalation attacks. Use sanitizers only in development and testing environments. From 2b02ba76403e6169308b207658257e5755c29936 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Wed, 1 Oct 2025 13:50:13 +0200 Subject: [PATCH 19/30] Improve document description Co-authored-by: Carlos Zoido --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 5aca1a985a3a..45afba9d54e0 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -15,7 +15,7 @@ Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as GCC, Clang, and MSVC support these tools through specific compiler and linker flags. -This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. +This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. Modeling and applying sanitizers using settings ----------------------------------------------- From 1f94538f9552d89c021002ab8752a4c807442b94 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 08:10:00 +0200 Subject: [PATCH 20/30] Remove Sanitizers with Conan hooks section Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 45afba9d54e0..0bdc8a9dbc75 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -281,48 +281,6 @@ Then, specify this toolchain file as part of your Conan profile: This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. -Managing sanitizers with Conan hooks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler -flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original -build files. - -For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the -``compiler.sanitizer`` setting: - -.. code-block:: python - :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py - - def pre_generate(conanfile): - sani = conanfile.settings.get_safe("compiler.sanitizer") - if not sani or sani == "null": - return - mapping = { - "Address": "address", - "Leak": "leak", - "Thread": "thread", - "Memory": "memory", - "UndefinedBehavior": "undefined", - "HardwareAssistanceAddress": "hwaddress", - "KernelAddress": "kernel-address", - "AddressUndefinedBehavior": "address,undefined", - "ThreadUndefinedBehavior": "thread,undefined", - } - fs = mapping.get(sani) - if not fs: - return - flag = f"-fsanitize={fs}" - for k in ("tools.build:cflags", "tools.build:cxxflags", - "tools.build:exelinkflags", "tools.build:sharedlinkflags"): - conanfile.conf.append(k, flag) - # Optional: better stack traces - conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") - -The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final -configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity -as it moves logic out of profile management. - Additional recommendations -------------------------- From c4e0c36bda5a5d871d6f9ee42de9fe161dbc27de Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 08:58:12 +0200 Subject: [PATCH 21/30] Add tables Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 0bdc8a9dbc75..cb7fcc47c56e 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -15,6 +15,34 @@ Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as GCC, Clang, and MSVC support these tools through specific compiler and linker flags. +Compiler Sanitizer Support Comparison +------------------------------------- + +The following table summarizes the support for various sanitizers across different compilers: + ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| Sanitizer | GCC | Clang | MSVC | Notes | ++========================================+=====+=======+======+=========================================+ +| **AddressSanitizer (ASan)** | ✅ | ✅ | ✅ | MSVC: Not supported for 32-bit targets | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **ThreadSanitizer (TSan)** | ✅ | ✅ | ❌ | Detects data races | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **MemorySanitizer (MSan)** | ❌ | ✅ | ❌ | Clang-only, requires `-O1` | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **UndefinedBehaviorSanitizer (UBSan)** | ✅ | ✅ | ❌ | Wide range of undefined behavior checks | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **LeakSanitizer (LSan)** | ✅ | ✅ | ❌ | Often integrated with ASan | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **HardwareAddressSanitizer (HWASan)** | ❌ | ✅ | ❌ | ARM64 only, lower overhead than ASan | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **KernelAddressSanitizer (KASan)** | ✅ | ✅ | ✅ | MSVC: Requires Windows 11 | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **DataFlowSanitizer (DFSan)** | ❌ | ✅ | ❌ | Dynamic data flow analysis | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **Control Flow Integrity (CFI)** | ❌ | ✅ | ✅ | MSVC: `/guard:cf` | ++----------------------------------------+-----+-------+------+-----------------------------------------+ + + This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. Modeling and applying sanitizers using settings @@ -56,6 +84,38 @@ The ``null`` value represents a build without sanitizers. The above models the u ``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. +Common Sanitizer Combinations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ++-------------------+-----+-------+------+-----------------------------------------+ +| Combination | GCC | Clang | MSVC | Compatibility | ++===================+=====+=======+======+=========================================+ +| **ASan + UBSan** | ✅ | ✅ | ❌ | Most common combination | ++-------------------+-----+-------+------+-----------------------------------------+ +| **TSan + UBSan** | ✅ | ✅ | ❌ | Good for multithreaded code | ++-------------------+-----+-------+------+-----------------------------------------+ +| **ASan + LSan** | ✅ | ✅ | ❌ | LSan often enabled by default with ASan | ++-------------------+-----+-------+------+-----------------------------------------+ +| **MSan + UBSan** | ❌ | ✅ | ❌ | Requires careful dependency management | ++-------------------+-----+-------+------+-----------------------------------------+ + +Compiler-Specific Flags +^^^^^^^^^^^^^^^^^^^^^^^ + ++-----------------------+------------------------+------------------------+----------------------+ +| Sanitizer | GCC Flag | Clang Flag | MSVC Flag | ++=======================+========================+========================+======================+ +| **AddressSanitizer** | `-fsanitize=address` | `-fsanitize=address` | `/fsanitize=address` | ++-----------------------+------------------------+------------------------+----------------------+ +| **ThreadSanitizer** | `-fsanitize=thread` | `-fsanitize=thread` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **MemorySanitizer** | N/A | `-fsanitize=memory` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **UndefinedBehavior** | `-fsanitize=undefined` | `-fsanitize=undefined` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **LeakSanitizer** | `-fsanitize=leak` | `-fsanitize=leak` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ + It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, refer to: From 3760901d4496532f5e04c0155c5271b8e6de6c6a Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 09:00:27 +0200 Subject: [PATCH 22/30] Fix warning message Signed-off-by: Uilian Ries --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index cb7fcc47c56e..229d92bc1f9b 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -8,8 +8,6 @@ Compiler sanitizers Using sanitizers in production, especially with programs that run with elevated privileges (for example, SUID binaries on Linux), is dangerous. The sanitizer runtime libraries depend on environment variables, which could allow privilege escalation attacks. Use sanitizers only in development and testing environments. - runtimes rely on environment variables that could enable privilege escalation attacks. - Use sanitizers only in development and testing environments. Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as From 92f25813e59541e75df22f9180206260d2c3590d Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 09:24:44 +0200 Subject: [PATCH 23/30] Reorganize reader flow 1 Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 107 ++++++++++-------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 229d92bc1f9b..148b518d41fa 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -5,18 +5,21 @@ Compiler sanitizers .. warning:: - Using sanitizers in production, especially with programs that run with elevated privileges (for example, SUID binaries on Linux), is dangerous. - The sanitizer runtime libraries depend on environment variables, which could allow privilege escalation attacks. - Use sanitizers only in development and testing environments. + Do not use sanitizers for production builds, especially for binaries with elevated privileges (e.g., SUID). + Sanitizer runtimes rely on environment variables and can enable privilege escalation. + Use only in development and testing. Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as GCC, Clang, and MSVC support these tools through specific compiler and linker flags. +This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. + Compiler Sanitizer Support Comparison ------------------------------------- -The following table summarizes the support for various sanitizers across different compilers: +Each compiler has different levels of support for various sanitizers, Clang being the most comprehensive so far. +To help you choose the right sanitizer for your needs and compiler, here is a summary of the most common ones: +----------------------------------------+-----+-------+------+-----------------------------------------+ | Sanitizer | GCC | Clang | MSVC | Notes | @@ -40,51 +43,15 @@ The following table summarizes the support for various sanitizers across differe | **Control Flow Integrity (CFI)** | ❌ | ✅ | ✅ | MSVC: `/guard:cf` | +----------------------------------------+-----+-------+------+-----------------------------------------+ - -This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. - -Modeling and applying sanitizers using settings ------------------------------------------------ - -If you want to model sanitizer options so that the package ID is affected by them, you can -:ref:`customize new compiler sub-settings `. You should not need -to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. - -This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use -the same binary package with or without sanitizers. This is ideal for development and debugging workflows. - -To better illustrate this, please clone the sources to recreate this project. You can find them in the -`examples2 repository `_ on GitHub: - -.. code-block:: bash - - git clone https://github.com/conan-io/examples2.git - cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers - -In this example we will see how to prepare Conan to use sanitizers in different ways. - -Configuring sanitizers as part of settings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you typically use a specific set of sanitizers or combinations for your builds, you can specify -a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: - -.. code-block:: yaml - :caption: settings_user.yml - :emphasize-lines: 3 - - compiler: - clang: - sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] - -This example defines a few common sanitizers. You can add any sanitizer your compiler supports. -The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, -``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, -``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. +Besides MSVC having more limited support for sanitizers, it encourages the community to vote for new features +at `Developer Community `_. Common Sanitizer Combinations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The sanitizers can often be combined to provide more comprehensive coverage, but not all combinations are supported by every compiler. +Here are some common combinations and their compatibility mostly used with GCC and Clang: + +-------------------+-----+-------+------+-----------------------------------------+ | Combination | GCC | Clang | MSVC | Compatibility | +===================+=====+=======+======+=========================================+ @@ -97,9 +64,17 @@ Common Sanitizer Combinations | **MSan + UBSan** | ❌ | ✅ | ❌ | Requires careful dependency management | +-------------------+-----+-------+------+-----------------------------------------+ +**Notes on combinations**: + +* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. +* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. + Compiler-Specific Flags ^^^^^^^^^^^^^^^^^^^^^^^ +Each compiler requires specific flags to enable the desired sanitizers. Here is a summary of the most common +sanitizers and their corresponding flags for GCC, Clang, and MSVC: + +-----------------------+------------------------+------------------------+----------------------+ | Sanitizer | GCC Flag | Clang Flag | MSVC Flag | +=======================+========================+========================+======================+ @@ -124,12 +99,34 @@ refer to: * GCC: `Instrumentation Options `_. * MSVC: `MSVC Sanitizers `_. -**Notes on combinations**: +Modeling and applying sanitizers using settings +----------------------------------------------- -* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. -* Address + UndefinedBehavior (UBSan) is a common and supported combination. -* Thread + UndefinedBehavior is also supported. -* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. +If you want to model sanitizer options so that the package ID is affected by them, you can +:ref:`customize new compiler sub-settings `. You should not need +to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. + +This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use +the same binary package with or without sanitizers. This is ideal for development and debugging workflows. + +Configuring sanitizers as part of settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you typically use a specific set of sanitizers or combinations for your builds, you can specify +a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: + +.. code-block:: yaml + :caption: settings_user.yml + :emphasize-lines: 3 + + compiler: + clang: + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + +This example defines a few common sanitizers. You can add any sanitizer your compiler supports. +The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, +``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, +``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. Adding sanitizers as part of the profile ---------------------------------------- @@ -180,6 +177,16 @@ pick up the flags defined in the ``[conf]`` section and apply them to the build. Building examples using sanitizers ---------------------------------- +To better illustrate this, first, please clone the sources to recreate this project. You can find them in the +`examples2 repository `_ on GitHub: + +.. code-block:: bash + + git clone https://github.com/conan-io/examples2.git + cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers + +In this example we will see how to prepare Conan to use sanitizers in different ways. + To show how to use sanitizers in your builds, let's consider two examples. .. note:: From 38524c3c4e4b4ec495163192ea015b267090c8d4 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 09:55:55 +0200 Subject: [PATCH 24/30] Reestructured page Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 123 ++++++++++-------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 148b518d41fa..3cf4896c0ee0 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -9,15 +9,26 @@ Compiler sanitizers Sanitizer runtimes rely on environment variables and can enable privilege escalation. Use only in development and testing. -Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, -dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as -GCC, Clang, and MSVC support these tools through specific compiler and linker flags. +Sanitizers are powerful runtime instrumentation tools that detect issues such as: + +* Buffer overflows (stack/heap), use-after-free, double-free +* Data races in multithreaded code +* Memory leaks +* Use of uninitialized memory +* A wide range of undefined behaviors + +Compilers such as GCC, Clang, and MSVC support sanitizers via compiler and linker flags. This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. Compiler Sanitizer Support Comparison ------------------------------------- +.. important:: + + Always rebuild all dependencies from source when enabling sanitizers to ensure consistent instrumentation + and to avoid false positives (particularly critical for MemorySanitizer). + Each compiler has different levels of support for various sanitizers, Clang being the most comprehensive so far. To help you choose the right sanitizer for your needs and compiler, here is a summary of the most common ones: @@ -46,6 +57,14 @@ To help you choose the right sanitizer for your needs and compiler, here is a su Besides MSVC having more limited support for sanitizers, it encourages the community to vote for new features at `Developer Community `_. +Also, you con consider the typical use cases for each sanitizer: + +* AddressSanitizer (ASan): Great default for memory errors; often combined with UBSan for broader coverage. +* ThreadSanitizer (TSan): Find data races in multithreaded code. +* MemorySanitizer (MSan): Detects uninitialized memory reads (Clang-only). Requires all dependencies to be instrumented. +* LeakSanitizer (LSan): Often included with ASan on Clang/GCC, can be enabled explicitly. Typically used to find memory leaks. +* UndefinedBehaviorSanitizer (UBSan): Catches many undefined behaviors; often combined with ASan. + Common Sanitizer Combinations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,8 +85,9 @@ Here are some common combinations and their compatibility mostly used with GCC a **Notes on combinations**: -* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. -* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. +* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) **are mutually exclusive with one another**. +* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies; + mixing with non-instrumented code leads to crashes/false positives. Compiler-Specific Flags ^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +110,7 @@ sanitizers and their corresponding flags for GCC, Clang, and MSVC: +-----------------------+------------------------+------------------------+----------------------+ It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, -refer to: +please refer to the official documentation for each compiler: * Clang: `AddressSanitizer `_, `ThreadSanitizer `_, @@ -99,8 +119,15 @@ refer to: * GCC: `Instrumentation Options `_. * MSVC: `MSVC Sanitizers `_. +Enabling Sanitizers +------------------- + +Conan cannot infer sanitizer flags from settings automatically. +You have to pass the appropriate compiler and linker flags (e.g., ``-fsanitize=`` or ``/fsanitize=address``) via profiles or toolchains. +Conan toolchains (e.g., ``CMakeToolchain``, ``MesonToolchain``) will propagate flags defined in ``[conf]`` sections. + Modeling and applying sanitizers using settings ------------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you want to model sanitizer options so that the package ID is affected by them, you can :ref:`customize new compiler sub-settings `. You should not need @@ -110,7 +137,7 @@ This approach is preferred because enabling a sanitizer alters the package ID, a the same binary package with or without sanitizers. This is ideal for development and debugging workflows. Configuring sanitizers as part of settings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you typically use a specific set of sanitizers or combinations for your builds, you can specify a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: @@ -129,7 +156,7 @@ The ``null`` value represents a build without sanitizers. The above models the u ``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. Adding sanitizers as part of the profile ----------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Another option is to add the sanitizer values as part of a profile. This way, you can easily switch between different configurations by using dedicated profiles. @@ -173,8 +200,40 @@ during the build process. It is necessary to pass the expected sanitizer flags a Conan's built-in toolchains (like ``CMakeToolchain`` and ``MesonToolchain``) will automatically pick up the flags defined in the ``[conf]`` section and apply them to the build. +Managing sanitizers with a CMake toolchain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. + +If you already have a :ref:`custom CMake toolchain file ` to manage compiler +and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. + +.. code-block:: cmake + :caption: cmake/my_toolchain.cmake + + # Apply to all targets; consider per-target options for finer control + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") + +Then, specify this toolchain file as part of your Conan profile: + +.. code-block:: ini + :caption: profiles/asan_ubsan + + include(default) + + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake -Building examples using sanitizers +This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. + +Building Examples Using Sanitizers ---------------------------------- To better illustrate this, first, please clone the sources to recreate this project. You can find them in the @@ -189,12 +248,6 @@ In this example we will see how to prepare Conan to use sanitizers in different To show how to use sanitizers in your builds, let's consider two examples. -.. note:: - - To build your project with a sanitizer, simply use the corresponding profile. - It is crucial to **rebuild all dependencies from source** to ensure they are also instrumented, - which prevents false positives and other issues. - AddressSanitizer: index out of bounds ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +275,7 @@ in an array, which should trigger ASan when running the program. } **Note:** The preprocessor check above is portable for GCC, Clang and MSVC. -The define ``__SANITIZE_ADDRESS__`` is present when ASan is active; +The define ``__SANITIZE_ADDRESS__`` is present when **ASan** is active; **To build and run this example using Conan:** @@ -310,42 +363,6 @@ It is supported by GCC and Clang. MSVC does not support UBSan. Address sanitizer enabled .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -Passing the information to the compiler or build system -------------------------------------------------------- - -Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. - -Managing sanitizers with a CMake toolchain -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you already have a :ref:`custom CMake toolchain file ` to manage compiler -and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. - -.. code-block:: cmake - :caption: cmake/my_toolchain.cmake - - # Apply to all targets; consider per-target options for finer control - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") - -Then, specify this toolchain file as part of your Conan profile: - -.. code-block:: ini - :caption: profiles/asan_ubsan - - include(default) - - [settings] - build_type=Debug - compiler.sanitizer=AddressUndefinedBehavior - - [conf] - tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake - -This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. - Additional recommendations -------------------------- From bb30880e163ecacf0e77d9f099328165f69bf43a Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 10:29:52 +0200 Subject: [PATCH 25/30] Add ABI compatibility section Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 3cf4896c0ee0..c70464870385 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -57,13 +57,13 @@ To help you choose the right sanitizer for your needs and compiler, here is a su Besides MSVC having more limited support for sanitizers, it encourages the community to vote for new features at `Developer Community `_. -Also, you con consider the typical use cases for each sanitizer: +Also, you can consider the typical use cases for each sanitizer: -* AddressSanitizer (ASan): Great default for memory errors; often combined with UBSan for broader coverage. -* ThreadSanitizer (TSan): Find data races in multithreaded code. -* MemorySanitizer (MSan): Detects uninitialized memory reads (Clang-only). Requires all dependencies to be instrumented. -* LeakSanitizer (LSan): Often included with ASan on Clang/GCC, can be enabled explicitly. Typically used to find memory leaks. -* UndefinedBehaviorSanitizer (UBSan): Catches many undefined behaviors; often combined with ASan. +* **AddressSanitizer (ASan)**: Great default for memory errors; often combined with UBSan for broader coverage. +* **ThreadSanitizer (TSan)**: Find data races in multithreaded code. +* **MemorySanitizer (MSan)**: Detects uninitialized memory reads (Clang-only). Requires all dependencies to be instrumented. +* **LeakSanitizer (LSan)**: Often included with ASan on Clang/GCC, can be enabled explicitly. Typically used to find memory leaks. +* **UndefinedBehaviorSanitizer (UBSan)**: Catches many undefined behaviors; often combined with ASan. Common Sanitizer Combinations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,6 +119,47 @@ please refer to the official documentation for each compiler: * GCC: `Instrumentation Options `_. * MSVC: `MSVC Sanitizers `_. +Binary Compatibility +-------------------- + +How sanitizers affect your binaries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sanitizers instrument your code at compile time, adding runtime checks and metadata. +This changes your binary's **Application Binary Interface (ABI)**, making instrumented code incompatible with non-instrumented code. + +**Key changes sanitizers make:** + +- **Memory layout**: Sanitizers add shadow memory, guard zones, or tracking metadata around your data +- **Function calls**: Standard library functions (``malloc``, ``free``, etc.) are wrapped or intercepted +- **Runtime dependencies**: Instrumented code requires sanitizer runtime libraries (``libasan``, ``libtsan``, etc.) +- **Linking**: Mixing instrumented and non-instrumented code can cause crashes, false positives, or undefined behavior + +Handling external code +^^^^^^^^^^^^^^^^^^^^^^ + +When using sanitizers, you must consider how to handle third-party dependencies. +As mixing instrumented and non-instrumented code can lead to issues, here are some strategies: + +**Always require full instrumentation:** + +- **MemorySanitizer (MSan)**: Changes function ABIs to pass shadow state. +- **DataFlowSanitizer (DFSan)**: Explicitly modifies the ABI by appending label parameters to functions. +- **ThreadSanitizer (TSan)**: Changes memory layout and intercepts synchronization primitives. + Some code may not be instrumented by ThreadSanitizer, but not recommended. + +**Usually require full instrumentation:** + +- **AddressSanitizer (ASan)**: Adds redzones and shadow memory; Works with non-instrumented code, but not recommended. +- **HardwareAddressSanitizer (HWASan)**: Similar to ASan but uses hardware tagging. Mixing is possible but not recommended. + +**Can often mix with non-instrumented code:** + +- **UndefinedBehaviorSanitizer (UBSan)**: Adds runtime checks for undefined behavior; Minimal ABI changes, safer to mix. +- **LeakSanitizer (LSan)**: Detects memory leaks at program exit; When standalone, has minimal ABI impact. + +For reliable results, **always** rebuild your entire dependency tree with the same sanitizer configuration. + Enabling Sanitizers ------------------- From a502719e1b062a9a3c3b0b3e594397156107dd63 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 11:19:26 +0200 Subject: [PATCH 26/30] Restore back sanitizers page Signed-off-by: Uilian Ries --- .../sanitizers/compiler_sanitizers.rst | 1994 ++++------------- 1 file changed, 436 insertions(+), 1558 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 797cc830dd76..c70464870385 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -1,1559 +1,437 @@ -From 355fd785ef13f12d303358af5c0e6ee536f8eb77 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Wed, 20 Aug 2025 11:12:06 +0200 -Subject: [PATCH 01/11] Add Sanitizers documentation - -Signed-off-by: Uilian Ries ---- - examples/dev_flow.rst | 1 + - .../sanitizers/compiler_sanitizers.rst | 198 ++++++++++++++++++ - 2 files changed, 199 insertions(+) - create mode 100644 examples/dev_flow/sanitizers/compiler_sanitizers.rst - -diff --git a/examples/dev_flow.rst b/examples/dev_flow.rst -index 4363e2e079b52f9a72f84f566321b3b9be8a3abd..21d7e0e947449cf9b6edc97bdd27b8d6f8178089 100644 ---- a/examples/dev_flow.rst -+++ b/examples/dev_flow.rst -@@ -8,4 +8,5 @@ Developer tools and flows - - dev_flow/debug/step_into_dependencies - dev_flow/debug/debugging_visual -+ dev_flow/sanitizers/compiler_sanitizers - dev_flow/tool_requires/mingw -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -new file mode 100644 -index 0000000000000000000000000000000000000000..f789417f15c30abaeaa4b1eea720bba5856b37e4 ---- /dev/null -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -0,0 +1,198 @@ -+.. _examples_dev_flow_sanitizers_compiler_sanitizers: -+ -+Compiler sanitizers -+=================== -+ -+Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, -+dangling pointers, and various types of undefined behavior. -+ -+Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. -+ -+This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. -+ -+Modeling and Applying Sanitizers using Settings -+------------------------------------------------ -+ -+If you want to model the sanitizer options so that the package id is affected by them, you have to -+:ref:`customize new compiler sub-settings`. You should not need -+modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` -+instead. -+ -+This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same -+binary package with or without sanitizers, which is ideal for development and debugging workflows. -+ -+To better illustrate this, please, first clone the sources to recreate this project. You can find them in the -+`examples2 repository `_ in GitHub: -+ -+.. code-block:: bash -+ -+ $ git clone https://github.com/conan-io/examples2.git -+ $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers -+ -+In this example we are going to see how to prepare Conan to use sanitizers in different ways. -+ -+ -+Configuring Sanitizers as Part of Settings -+########################################## -+ -+If you typically use a specific set of sanitizers or combinations for your builds, you can specify -+them as a list of values. For example, with Clang, you might do the following: -+ -+.. code-block:: yaml -+ :caption: *settings_user.yml* -+ :emphasize-lines: 6 -+ -+ compiler: -+ clang: -+ sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] -+ -+Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, -+``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with -+``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. -+ -+It seems be a large number of options, but for Clang, these are only a portion. -+To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. -+The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. -+For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. -+ -+Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. -+ -+Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. -+In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. -+ -+Adding Sanitizers as Part of the Profile -+######################################## -+ -+An option would be to add the sanitizer values as part of the profile. -+This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. -+ -+.. code-block:: ini -+ :caption: *~/.conan/profiles/asan* -+ :emphasize-lines: 6 -+ -+ include(default) -+ -+ [settings] -+ compiler.sanitizer=Address -+ -+ [conf] -+ tools.build:cflags=['-fsanitize=address'] -+ tools.build:cxxflags=['-fsanitize=address'] -+ -+The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. -+It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. -+ -+ -+Passing the information to the compiler or build system -+------------------------------------------------------- -+ -+Here again, we have multiple choices to pass sanitizers information to the compiler or build system. -+ -+Using from custom profiles -+########################## -+ -+It is possible to have different custom profiles defining the compiler sanitizer setting and -+environment variables to inject that information to the compiler, and then passing those profiles to -+Conan commands. An example of this would be a profile like: -+ -+.. code-block:: text -+ :caption: *address_sanitizer_profile* -+ :emphasize-lines: 10,12,13,14 -+ -+ [settings] -+ os=Macos -+ os_build=Macos -+ arch=x86_64 -+ arch_build=x86_64 -+ compiler=apple-clang -+ compiler.version=10.0 -+ compiler.libcxx=libc++ -+ build_type=Release -+ compiler.sanitizer=Address -+ [env] -+ CFLAGS=-fsanitize=address -+ CXXFLAGS=-fsanitize=address -+ LDFLAGS=-fsanitize=address -+ -+Then calling :command:`conan create . -pr address_sanitizer_profile` would inject -+``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. -+ -+Managing sanitizer settings with the build system -+################################################# -+ -+Another option is to make use of the information that is propagated to the *conan generator*. For -+example, if we are using CMake we could use the information from the *CMakeLists.txt* to append -+the flags to the compiler settings like this: -+ -+.. code-block:: cmake -+ :caption: *CMakeLists.txt* -+ -+ cmake_minimum_required(VERSION 3.2) -+ project(SanitizerExample) -+ set (CMAKE_CXX_STANDARD 11) -+ include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) -+ conan_basic_setup() -+ set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) -+ if(SANITIZER) -+ if(SANITIZER MATCHES "(Address)") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) -+ endif() -+ endif() -+ add_executable(sanit_example src/main.cpp) -+ -+ -+The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable -+with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of -+the variable. -+ -+ -+Using conan Hooks to set compiler environment variables -+####################################################### -+ -+.. warning:: -+ -+ This way of adding sanitizers is recommended just for testing purposes. In general, it's not a -+ good practice to inject this in the environment using a Conan hook. It's much better explicitly -+ defining this in the profiles. -+ -+.. important:: -+ -+ Take into account that the package ID doesn't encode information about the environment, -+ so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. -+ -+ -+If you are not interested in modelling the settings in the Conan package you can use a -+Hook to modify the environment variable and apply the sanitizer -+flags to the build. It could be something like: -+ -+.. code-block:: python -+ :caption: *sanitizer_hook.py* -+ -+ import os -+ -+ -+ class SanitizerHook(object): -+ def __init__(self): -+ self._old_cxx_flags = None -+ -+ def set_sanitize_address_flag(self): -+ self._old_cxx_flags = os.environ.get("CXXFLAGS") -+ flags_str = self._old_cxx_flags or "" -+ os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" -+ -+ def reset_sanitize_address_flag(self): -+ if self._old_cxx_flags is None: -+ del os.environ["CXXFLAGS"] -+ else: -+ os.environ["CXXFLAGS"] = self._old_cxx_flags -+ -+ -+ sanitizer = SanitizerHook() -+ -+ -+ def pre_build(output, conanfile, **kwargs): -+ sanitizer.set_sanitize_address_flag() -+ -+ -+ def post_build(output, conanfile, **kwargs): -+ sanitizer.reset_sanitize_address_flag() --- -2.51.0 - - -From 84ba72d20e0024ac44eccb248d1d748efe28da61 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Wed, 20 Aug 2025 11:22:31 +0200 -Subject: [PATCH 02/11] Add Sanitizers - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 128 ++++-------------- - 1 file changed, 24 insertions(+), 104 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index f789417f15c30abaeaa4b1eea720bba5856b37e4..7a3fe106b92d8c9e2b039157a46954e842de2d68 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -3,6 +3,12 @@ - Compiler sanitizers - =================== - -+.. warning:: -+ -+ Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime -+ relies on environment variables that could enable privilege escalation attacks. -+ Use sanitizers only in development and testing environments. -+ - Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, - dangling pointers, and various types of undefined behavior. - -@@ -40,7 +46,7 @@ them as a list of values. For example, with Clang, you might do the following: - - .. code-block:: yaml - :caption: *settings_user.yml* -- :emphasize-lines: 6 -+ :emphasize-lines: 3 - - compiler: - clang: -@@ -82,117 +88,31 @@ This way, you can easily switch between different sanitizer configurations by us - The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. - It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. - -+Building Examples Using Sanitizers -+---------------------------------- - --Passing the information to the compiler or build system --------------------------------------------------------- -- --Here again, we have multiple choices to pass sanitizers information to the compiler or build system. -- --Using from custom profiles --########################## -- --It is possible to have different custom profiles defining the compiler sanitizer setting and --environment variables to inject that information to the compiler, and then passing those profiles to --Conan commands. An example of this would be a profile like: -- --.. code-block:: text -- :caption: *address_sanitizer_profile* -- :emphasize-lines: 10,12,13,14 -- -- [settings] -- os=Macos -- os_build=Macos -- arch=x86_64 -- arch_build=x86_64 -- compiler=apple-clang -- compiler.version=10.0 -- compiler.libcxx=libc++ -- build_type=Release -- compiler.sanitizer=Address -- [env] -- CFLAGS=-fsanitize=address -- CXXFLAGS=-fsanitize=address -- LDFLAGS=-fsanitize=address -- --Then calling :command:`conan create . -pr address_sanitizer_profile` would inject --``-fsanitize=address`` to the build through the ``CFLAGS``, ``CXXFLAGS``, and ``LDFLAGS`` environment variables. -- --Managing sanitizer settings with the build system --################################################# -- --Another option is to make use of the information that is propagated to the *conan generator*. For --example, if we are using CMake we could use the information from the *CMakeLists.txt* to append --the flags to the compiler settings like this: -- --.. code-block:: cmake -- :caption: *CMakeLists.txt* -+Address Sanitizer: Index Out of Bounds -+###################################### - -- cmake_minimum_required(VERSION 3.2) -- project(SanitizerExample) -- set (CMAKE_CXX_STANDARD 11) -- include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) -- conan_basic_setup() -- set(SANITIZER ${CONAN_SETTINGS_COMPILER_SANITIZER}) -- if(SANITIZER) -- if(SANITIZER MATCHES "(Address)") -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address" ) -- endif() -- endif() -- add_executable(sanit_example src/main.cpp) -+**TODO** - -+Undefined Sanitizer: Signed Integer Overflow -+############################################ - --The sanitizer setting is propagated to CMake as the ``CONAN_SETTINGS_COMPILER_SANITIZER`` variable --with a value equals to ``"Address"`` and we can set the behavior in CMake depending on the value of --the variable. -+**TODO** - -+Passing the information to the compiler or build system -+------------------------------------------------------- - --Using conan Hooks to set compiler environment variables --####################################################### -- --.. warning:: -- -- This way of adding sanitizers is recommended just for testing purposes. In general, it's not a -- good practice to inject this in the environment using a Conan hook. It's much better explicitly -- defining this in the profiles. -- --.. important:: -- -- Take into account that the package ID doesn't encode information about the environment, -- so different binaries due to different `CXX_FLAGS` would be considered by Conan as the same package. -- -- --If you are not interested in modelling the settings in the Conan package you can use a --Hook to modify the environment variable and apply the sanitizer --flags to the build. It could be something like: -- --.. code-block:: python -- :caption: *sanitizer_hook.py* -- -- import os -- -- -- class SanitizerHook(object): -- def __init__(self): -- self._old_cxx_flags = None -- -- def set_sanitize_address_flag(self): -- self._old_cxx_flags = os.environ.get("CXXFLAGS") -- flags_str = self._old_cxx_flags or "" -- os.environ["CXXFLAGS"] = flags_str + " -fsanitize=address" -- -- def reset_sanitize_address_flag(self): -- if self._old_cxx_flags is None: -- del os.environ["CXXFLAGS"] -- else: -- os.environ["CXXFLAGS"] = self._old_cxx_flags -- -+Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. - -- sanitizer = SanitizerHook() -+Managing Sanitizer with CMake Toolchain -+####################################### - -+**TODO** - -- def pre_build(output, conanfile, **kwargs): -- sanitizer.set_sanitize_address_flag() - -+Mananaging Sanitizer with Conan Hooks -+##################################### - -- def post_build(output, conanfile, **kwargs): -- sanitizer.reset_sanitize_address_flag() -+**TODO** -\ No newline at end of file --- -2.51.0 - - -From 6c6a71ec7ce9af99c8463c09016d01d1e56fbe54 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Thu, 21 Aug 2025 09:42:11 +0200 -Subject: [PATCH 03/11] Add more sections - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 140 +++++++++++++++++- - 1 file changed, 136 insertions(+), 4 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 7a3fe106b92d8c9e2b039157a46954e842de2d68..0c758844264a8ebef2432975401aaa471021ddf1 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -74,7 +74,7 @@ This way, you can easily switch between different sanitizer configurations by us - - .. code-block:: ini - :caption: *~/.conan/profiles/asan* -- :emphasize-lines: 6 -+ :emphasize-lines: 7 - - include(default) - -@@ -84,22 +84,154 @@ This way, you can easily switch between different sanitizer configurations by us - [conf] - tools.build:cflags=['-fsanitize=address'] - tools.build:cxxflags=['-fsanitize=address'] -+ tools.build:exelinkflags=['-fsanitize=address'] - --The Conan client is capable to deduce the necessary flags from the profile and apply them during the build process. -+The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. - It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. - - Building Examples Using Sanitizers - ---------------------------------- - -+To show how to use sanitizers in your builds, let's consider a couple of examples. -+ - Address Sanitizer: Index Out of Bounds - ###################################### - --**TODO** -+In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds -+index in an array, which should trigger the Address Sanitizer when running the program. -+ -+The following code demonstrates this: -+ -+.. code-block:: cpp -+ :caption: *index_out_of_bounds/main.cpp* -+ :emphasize-lines: 11 -+ -+ #include -+ #include -+ -+ int main() { -+ #ifdef __SANITIZE_ADDRESS__ -+ std::cout << "Address sanitizer enabled\n"; -+ #else -+ std::cout << "Address sanitizer not enabled\n"; -+ #endif -+ -+ int foo[100]; -+ foo[100] = 42; // Out-of-bounds write -+ -+ return EXIT_SUCCESS; -+ } -+ -+The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when -+running the produced application. It's supported by GCC, Clang and MSVC compilers. -+ -+To build this example, you can use Conan to invoke CMake and perform the build. -+ -+.. code-block:: bash -+ -+ conan export index_out_of_bounds/ -+ conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing -+ -+ -+Here we are using Conan to export the recipe and build the project. -+The profile file `profiles/asan` was demonstrated already and will merge with the default profile -+from your configuration. The resulting build will produce an executable in a specific package folder, -+in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, -+then run the executable: -+ -+.. code-block:: text -+ -+ source index_out_of_bounds/install/conanrun.sh -+ index_out_of_bounds -+ -+ Address sanitizer enabled -+ ================================================================= -+ ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 -+ WRITE of size 4 at 0x7fffbe04a6d0 thread T0 -+ #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) -+ #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 -+ #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 -+ #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) -+ -+ Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame -+ #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) -+ -+ This frame has 1 object(s): -+ [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable -+ HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork -+ (longjmp and C++ exceptions *are* supported) -+ SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main -+ -+Once running the example, you should see an error message from the Address Sanitizer indicating the -+out-of-bounds. The message is simplified here, but it provides useful information about the error, -+including the expected index of bounds error. -+ - - Undefined Sanitizer: Signed Integer Overflow - ############################################ - --**TODO** -+This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. -+It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. -+For this example, we will be using the following Conan profile: -+ -+.. code-block:: ini -+ :caption: *~/.conan/profiles/asan_ubsan* -+ :emphasize-lines: 7 -+ -+ include(default) -+ -+ [settings] -+ compiler.sanitizer=AddressUndefinedBehavior -+ -+ [conf] -+ tools.build:cflags=['-fsanitize=address,undefined'] -+ tools.build:cxxflags=['-fsanitize=address,undefined'] -+ tools.build:exelinkflags=['-fsanitize=address,undefined'] -+ -+It's important to mention it only works for GCC and Clang compilers, -+as MSVC does not support the Undefined Behavior Sanitizer yet. -+ -+The source code for this example is as follows: -+ -+.. code-block:: cpp -+ :caption: *signed_integer_overflow/main.cpp* -+ :emphasize-lines: 12 -+ -+ #include -+ #include -+ #include -+ -+ int main(int argc, char* argv[]) { -+ #ifdef __SANITIZE_ADDRESS__ -+ std::cout << "Address sanitizer enabled\n"; -+ #else -+ std::cout << "Address sanitizer not enabled\n"; -+ #endif -+ -+ int foo = 0x7fffffff; -+ foo += argc; // Signed integer overflow -+ -+ return EXIT_SUCCESS; -+ } -+ -+In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. -+ -+As next step, the code can be built using Conan and CMake, similar to the previous example: -+ -+.. code-block:: bash -+ -+ conan export signed_integer_overflow/ -+ conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing -+ -+ -+Once the project built successfully, you can run the example with the sanitizers enabled: -+ -+.. code-block:: bash -+ -+ conan build signed_integer_overflow/install -+ ./build/signed_integer_overflow -+ -+This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z - - Passing the information to the compiler or build system - ------------------------------------------------------- --- -2.51.0 - - -From 9ef3092aa6dd092b1c1ae36f28753fb5703df312 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Fri, 22 Aug 2025 09:26:52 +0200 -Subject: [PATCH 04/11] Sanitizer setting is optional - -Signed-off-by: Uilian Ries ---- - examples/dev_flow/sanitizers/compiler_sanitizers.rst | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 0c758844264a8ebef2432975401aaa471021ddf1..28c050f3c660f5066f49d202730d3f985de04fff 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -50,7 +50,7 @@ them as a list of values. For example, with Clang, you might do the following: - - compiler: - clang: -- sanitizer: [None, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] -+ sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] - - Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, - ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with -@@ -63,9 +63,6 @@ For MSVC, the available sanitizers are more limited, and you can find the comple - - Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. - --Be aware once ``setting_user.yml`` is present in your Conan home, it will affect all your projects using Conan, asking for the setting ``compiler.sanitizer`` always. --In order to disable it, just remove the ``settings_user.yml`` file from your Conan home. -- - Adding Sanitizers as Part of the Profile - ######################################## - --- -2.51.0 - - -From 057ca97b64b1a0b500540be7402933d88ce423fd Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Fri, 22 Aug 2025 11:54:07 +0200 -Subject: [PATCH 05/11] Add toolchain and hook section - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 73 +++++++++++++++++-- - 1 file changed, 65 insertions(+), 8 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 28c050f3c660f5066f49d202730d3f985de04fff..3fca65f5f3e14a86cff0b21bbf5feabe3a0681d7 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -84,7 +84,8 @@ This way, you can easily switch between different sanitizer configurations by us - tools.build:exelinkflags=['-fsanitize=address'] - - The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. --It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value. -+It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value -+as part of the compiler flags. - - Building Examples Using Sanitizers - ---------------------------------- -@@ -228,20 +229,76 @@ Once the project built successfully, you can run the example with the sanitizers - conan build signed_integer_overflow/install - ./build/signed_integer_overflow - --This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues.z -+This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. - --Passing the information to the compiler or build system --------------------------------------------------------- -+.. code-block:: text -+ -+ source signed_integer_overflow/install/conanrun.sh -+ signed_integer_overflow -+ -+ Address sanitizer enabled -+ /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -+ -+The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. -+ -+Passing then Information to the Compiler or Build System -+-------------------------------------------------------- - - Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. - - Managing Sanitizer with CMake Toolchain - ####################################### - --**TODO** -+For those cases when a company or developer has a :ref:`custom CMake toolchain file ` -+to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers -+instead of using profiles to configure extra compiler flags. -+ -+For example, you can create a CMake toolchain file like this: -+ -+.. code-block:: cmake -+ :caption: *cmake/my_toolchain.cmake* -+ -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") -+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") -+ -+Then, you can specify this toolchain file as part of your Conan profile as well: -+ -+.. code-block:: ini -+ :caption: *profiles/asan_ubsan* -+ -+ include(default) -+ -+ [settings] -+ compiler.sanitizer=AddressUndefinedBehavior -+ -+ [conf] -+ tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake -+ -+This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. -+ -+Managing Sanitizer with Conan Hooks -+################################### -+ -+Another approach to manage sanitizers is by using :ref:`Conan hooks `. -+Using hooks, you can inject compiler flags on-the-fly during the build process, -+allowing for more dynamic configurations without modifying the original build files. -+ -+For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the -+``compiler.sanitizer`` setting. - -+.. code-block:: python -+ :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py - --Mananaging Sanitizer with Conan Hooks --##################################### -+ def pre_generate(conanfile): -+ if conanfile.settings.get_safe("compiler.sanitizer"): -+ sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} -+ if conanfile.settings.compiler.sanitizer in sanitizer: -+ flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" -+ conanfile.conf.append("tools.build:cflags", flag) -+ conanfile.conf.append("tools.build:cxxflags", flag) -+ conanfile.conf.append("tools.build:exelinkflags", flag) - --**TODO** -\ No newline at end of file -+The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume -+the respective configuration for the compiler flags. This approach allows for more dynamic configurations -+as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the -+logic out for the profile management. --- -2.51.0 - - -From 14dfdcfe59c721ad5306402bf1a55ff27d698b28 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Fri, 22 Aug 2025 15:04:03 +0200 -Subject: [PATCH 06/11] Improve description - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 458 ++++++++++-------- - 1 file changed, 255 insertions(+), 203 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 3fca65f5f3e14a86cff0b21bbf5feabe3a0681d7..14a582d6a0c0f04a82c57b6e80150f4c616955f9 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -1,3 +1,5 @@ -+### Compiler sanitizers -+ - .. _examples_dev_flow_sanitizers_compiler_sanitizers: - - Compiler sanitizers -@@ -5,300 +7,350 @@ Compiler sanitizers - - .. warning:: - -- Using sanitizers in production with suid binaries is dangerous, as the libsanitizer runtime -- relies on environment variables that could enable privilege escalation attacks. -- Use sanitizers only in development and testing environments. -- --Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, memory leaks, --dangling pointers, and various types of undefined behavior. -+ Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer -+ runtimes rely on environment variables that could enable privilege escalation attacks. -+ Use sanitizers only in development and testing environments. - --Compilers such as GCC, Clang and MSVC support these tools through specific compiler and linker flags. -+Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, data races, memory leaks, -+dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as -+GCC, Clang, and MSVC support these tools through specific compiler and linker flags. - --This example explains a recommended approach for integrating compiler sanitizers into your Conan 2.x workflow. -+This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. - --Modeling and Applying Sanitizers using Settings -------------------------------------------------- -+Modeling and applying sanitizers using settings -+----------------------------------------------- - --If you want to model the sanitizer options so that the package id is affected by them, you have to --:ref:`customize new compiler sub-settings`. You should not need --modify ``settings.yml`` directly, but adding :ref:`the settings_user.yml ` --instead. -+If you want to model sanitizer options so that the package ID is affected by them, you can -+:ref:`customize new compiler sub-settings `. You should not need -+to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. - --This approach is preferred because it ensures that enabling a sanitizer alters the package ID, allowing you to use the same --binary package with or without sanitizers, which is ideal for development and debugging workflows. -+This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use -+the same binary package with or without sanitizers. This is ideal for development and debugging workflows. - --To better illustrate this, please, first clone the sources to recreate this project. You can find them in the --`examples2 repository `_ in GitHub: -+To better illustrate this, please clone the sources to recreate this project. You can find them in the -+`examples2 repository `_ on GitHub: - - .. code-block:: bash - -- $ git clone https://github.com/conan-io/examples2.git -- $ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers -- --In this example we are going to see how to prepare Conan to use sanitizers in different ways. -+ git clone https://github.com/conan-io/examples2.git -+ cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers - -+In this example we will see how to prepare Conan to use sanitizers in different ways. - --Configuring Sanitizers as Part of Settings --########################################## -+Configuring sanitizers as part of settings -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - If you typically use a specific set of sanitizers or combinations for your builds, you can specify --them as a list of values. For example, with Clang, you might do the following: -+a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: - - .. code-block:: yaml -- :caption: *settings_user.yml* -- :emphasize-lines: 3 -+ :caption: settings_user.yml -+ :emphasize-lines: 3 - -- compiler: -- clang: -- sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] -+ compiler: -+ clang: -+ sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] - --Here you have modeled the use of ``-fsanitize=address``, ``-fsanitize=thread``, --``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, the combination of ``-fsanitize=address`` with --``-fsanitize=undefined`` and ``-fsanitize=thread`` with ``-fsanitize=undefined``. -+This example defines a few common sanitizers. You can add any sanitizer your compiler supports. -+The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, -+``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, -+``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. - --It seems be a large number of options, but for Clang, these are only a portion. --To obtain the complete list of available sanitizers, you can refer to the `Clang documentation `_. --The GCC supports a similar number of sanitizers, and you can find the complete list in the `GCC documentation `_. --For MSVC, the available sanitizers are more limited, and you can find the complete list in the `MSVC documentation `_. -+It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, -+refer to: - --Note that not all sanitizer combinations are possible, for example, with Clang, you cannot use more than one of the Address, Thread, or Memory sanitizers in the same program. -+* Clang: `AddressSanitizer `_, -+ `ThreadSanitizer `_, -+ `MemorySanitizer `_, -+ `UndefinedBehaviorSanitizer `_. -+* GCC: `Instrumentation Options `_. -+* MSVC: `MSVC Sanitizers `_. - --Adding Sanitizers as Part of the Profile --######################################## -+**Notes on combinations**: - --An option would be to add the sanitizer values as part of the profile. --This way, you can easily switch between different sanitizer configurations by using different dedicated profiles. -+* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) are mutually exclusive with one another. -+* Address + UndefinedBehavior (UBSan) is a common and supported combination. -+* Thread + UndefinedBehavior is also supported. -+* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies. - --.. code-block:: ini -- :caption: *~/.conan/profiles/asan* -- :emphasize-lines: 7 -- -- include(default) -+Adding sanitizers as part of the profile -+---------------------------------------- - -- [settings] -- compiler.sanitizer=Address -+Another option is to add the sanitizer values as part of a profile. This way, you can easily switch between -+different configurations by using dedicated profiles. - -- [conf] -- tools.build:cflags=['-fsanitize=address'] -- tools.build:cxxflags=['-fsanitize=address'] -- tools.build:exelinkflags=['-fsanitize=address'] -+.. code-block:: ini -+ :caption: compiler_sanitizers/profiles/asan - --The Conan client is not capable to deduce the necessary flags from the settings and apply them during the build process. --It's necessary to pass those expected sanitizer flags according to the setting ``compiler.sanitizer`` value --as part of the compiler flags. -+ include(default) - --Building Examples Using Sanitizers ------------------------------------ -+ [settings] -+ build_type=Debug -+ compiler.sanitizer=Address - --To show how to use sanitizers in your builds, let's consider a couple of examples. -+ [conf] -+ tools.build:cflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] -+ tools.build:cxxflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] -+ tools.build:exelinkflags+=["-fsanitize=address"] -+ tools.build:sharedlinkflags+=["-fsanitize=address"] - --Address Sanitizer: Index Out of Bounds --###################################### -+ [runenv] -+ ASAN_OPTIONS="halt_on_error=1:detect_leaks=1" - --In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds --index in an array, which should trigger the Address Sanitizer when running the program. -+For Visual Studio (MSVC) we can obtain an equivalent profile for AddressSanitizer: - --The following code demonstrates this: -+.. code-block:: ini -+ :caption: ~/.conan/profiles/asan - --.. code-block:: cpp -- :caption: *index_out_of_bounds/main.cpp* -- :emphasize-lines: 11 -+ include(default) - -- #include -- #include -+ [settings] -+ build_type=Debug -+ compiler.sanitizer=Address - -- int main() { -- #ifdef __SANITIZE_ADDRESS__ -- std::cout << "Address sanitizer enabled\n"; -- #else -- std::cout << "Address sanitizer not enabled\n"; -- #endif -+ [conf] -+ tools.build:cxxflags+=["/fsanitize=address", "/Zi"] -+ tools.build:exelinkflags+=["/fsanitize=address"] - -- int foo[100]; -- foo[100] = 42; // Out-of-bounds write -+The Conan client is not capable of deducing the necessary flags from the settings and applying them automatically -+during the build process. It is necessary to pass the expected sanitizer flags according to the -+``compiler.sanitizer`` value as part of the compiler and linker flags. -+Conan's built-in toolchains (like ``CMakeToolchain`` and ``MesonToolchain``) will automatically -+pick up the flags defined in the ``[conf]`` section and apply them to the build. - -- return EXIT_SUCCESS; -- } - --The definition ``__SANITIZE_ADDRESS__`` is used to check if the Address Sanitizer is enabled when --running the produced application. It's supported by GCC, Clang and MSVC compilers. -+Building examples using sanitizers -+---------------------------------- - --To build this example, you can use Conan to invoke CMake and perform the build. -+To show how to use sanitizers in your builds, let's consider two examples. - --.. code-block:: bash -+.. note:: - -- conan export index_out_of_bounds/ -- conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing -+ To build your project with a sanitizer, simply use the corresponding profile. -+ It is crucial to **rebuild all dependencies from source** to ensure they are also instrumented, -+ which prevents false positives and other issues. - -+AddressSanitizer: index out of bounds -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - --Here we are using Conan to export the recipe and build the project. --The profile file `profiles/asan` was demonstrated already and will merge with the default profile --from your configuration. The resulting build will produce an executable in a specific package folder, --in order to access it, you can use the script produced by the ``VirtualRunEnv`` generator, --then run the executable: -+In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds index -+in an array, which should trigger ASan when running the program. - --.. code-block:: text -+.. code-block:: cpp -+ :caption: index_out_of_bounds/main.cpp -+ :emphasize-lines: 11 - -- source index_out_of_bounds/install/conanrun.sh -- index_out_of_bounds -+ #include -+ #include - -- Address sanitizer enabled -- ================================================================= -- ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 at pc 0x5dad4506e2eb bp 0x7fffbe04a500 sp 0x7fffbe04a4f0 -- WRITE of size 4 at 0x7fffbe04a6d0 thread T0 -- #0 0x5dad4506e2ea in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) -- #1 0x731331629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 -- #2 0x731331629e3f in __libc_start_main_impl ../csu/libc-start.c:392 -- #3 0x5dad4506e3d4 in _start (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x13d4) -+ int main() { -+ #ifdef __SANITIZE_ADDRESS__ -+ std::cout << "Address sanitizer enabled\n"; -+ #else -+ std::cout << "Address sanitizer not enabled\n"; -+ #endif - -- Address 0x7fffbe04a6d0 is located in stack of thread T0 at offset 448 in frame -- #0 0x5dad4506e1ef in main (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x11ef) -+ int foo[100]; -+ foo[100] = 42; // Out-of-bounds write - -- This frame has 1 object(s): -- [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable -- HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork -- (longjmp and C++ exceptions *are* supported) -- SUMMARY: AddressSanitizer: stack-buffer-overflow (.../examples2/examples/dev_flow/sanitizers/compiler_sanitizers/index_out_of_bounds/build/Debug/index_out_of_bounds+0x12ea) in main -+ return EXIT_SUCCESS; -+ } - --Once running the example, you should see an error message from the Address Sanitizer indicating the --out-of-bounds. The message is simplified here, but it provides useful information about the error, --including the expected index of bounds error. -+**Note:** The preprocessor check above is portable for GCC, Clang and MSVC. -+The define ``__SANITIZE_ADDRESS__`` is present when ASan is active; - -+**To build and run this example using Conan:** - --Undefined Sanitizer: Signed Integer Overflow --############################################ -+.. code-block:: bash - --This example demonstrates how to use the Undefined Behavior Sanitizer to detect signed integer overflow. --It combines the usage of two sanitizers at same time: Address Sanitizer and Undefined Behavior Sanitizer. --For this example, we will be using the following Conan profile: -+ conan export index_out_of_bounds/ -+ conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing -+ # Activate run environment to ensure sanitizer runtime and paths are set -+ source index_out_of_bounds/install/conanrun.sh -+ index_out_of_bounds - --.. code-block:: ini -- :caption: *~/.conan/profiles/asan_ubsan* -- :emphasize-lines: 7 -+**Expected output (abbreviated):** - -- include(default) -+.. code-block:: text - -- [settings] -- compiler.sanitizer=AddressUndefinedBehavior -+ Address sanitizer enabled -+ ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 ... -+ WRITE of size 4 at 0x7fffbe04a6d0 thread T0 -+ #0 ... in main .../index_out_of_bounds+0x12ea -+ ... -+ SUMMARY: AddressSanitizer: stack-buffer-overflow ... in main -+ This frame has 1 object(s): -+ [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable - -- [conf] -- tools.build:cflags=['-fsanitize=address,undefined'] -- tools.build:cxxflags=['-fsanitize=address,undefined'] -- tools.build:exelinkflags=['-fsanitize=address,undefined'] -+UndefinedBehaviorSanitizer: signed integer overflow -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - --It's important to mention it only works for GCC and Clang compilers, --as MSVC does not support the Undefined Behavior Sanitizer yet. -+This example demonstrates how to use UBSan to detect signed integer overflow. It combines ASan and UBSan. -+Create a dedicated profile: - --The source code for this example is as follows: -+.. code-block:: ini -+ :caption: ~/.conan/profiles/asan_ubsan -+ :emphasize-lines: 7 - --.. code-block:: cpp -- :caption: *signed_integer_overflow/main.cpp* -- :emphasize-lines: 12 -+ include(default) - -- #include -- #include -- #include -+ [settings] -+ build_type=Debug -+ compiler.sanitizer=AddressUndefinedBehavior - -- int main(int argc, char* argv[]) { -- #ifdef __SANITIZE_ADDRESS__ -- std::cout << "Address sanitizer enabled\n"; -- #else -- std::cout << "Address sanitizer not enabled\n"; -- #endif -+ [conf] -+ tools.build:cflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] -+ tools.build:cxxflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] -+ tools.build:exelinkflags+=["-fsanitize=address,undefined"] -+ tools.build:sharedlinkflags+=["-fsanitize=address,undefined"] - -- int foo = 0x7fffffff; -- foo += argc; // Signed integer overflow -+It is supported by GCC and Clang. MSVC does not support UBSan. - -- return EXIT_SUCCESS; -- } -+**Source code:** - --In this example, it's intentionally causing a signed integer overflow by adding the command line argument count to a large integer value. -+.. code-block:: cpp -+ :caption: signed_integer_overflow/main.cpp -+ :emphasize-lines: 14 - --As next step, the code can be built using Conan and CMake, similar to the previous example: -+ #include -+ #include -+ #include - --.. code-block:: bash -+ int main() { -+ #ifdef __SANITIZE_ADDRESS__ -+ std::cout << "Address sanitizer enabled\n"; -+ #else -+ std::cout << "Address sanitizer not enabled\n"; -+ #endif - -- conan export signed_integer_overflow/ -- conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan -of signed_integer_overflow/install --build=missing -+ int x = INT_MAX; -+ x += 42; // signed integer overflow - -+ return EXIT_SUCCESS; -+ } - --Once the project built successfully, you can run the example with the sanitizers enabled: -+**Build and run:** - - .. code-block:: bash - -- conan build signed_integer_overflow/install -- ./build/signed_integer_overflow -+ conan export signed_integer_overflow/ -+ conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing -+ source signed_integer_overflow/install/conanrun.sh -+ signed_integer_overflow - --This should trigger the Address and Undefined Behavior Sanitizers, and you should see output indicating any detected issues. -+**Expected output (abbreviated):** - - .. code-block:: text - -- source signed_integer_overflow/install/conanrun.sh -- signed_integer_overflow -- -- Address sanitizer enabled -- /root/.conan2/p/b/signe47ab122831752/b/main.cpp:13:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' -- --The output indicates that the Address Sanitizer is enabled and reports a runtime error due to signed integer overflow. -- --Passing then Information to the Compiler or Build System ---------------------------------------------------------- -+ Address sanitizer enabled -+ .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' - --Besides using Conan profiles to manage sanitizer settings, you can also use different approaches. -+Passing the information to the compiler or build system -+------------------------------------------------------- - --Managing Sanitizer with CMake Toolchain --####################################### -+Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. - --For those cases when a company or developer has a :ref:`custom CMake toolchain file ` --to manage compiler and build options already, it can be used to pass the necessary flags to enable sanitizers --instead of using profiles to configure extra compiler flags. -+Managing sanitizers with a CMake toolchain -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - --For example, you can create a CMake toolchain file like this: -+If you already have a :ref:`custom CMake toolchain file ` to manage compiler -+and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. - - .. code-block:: cmake -- :caption: *cmake/my_toolchain.cmake* -+ :caption: cmake/my_toolchain.cmake - -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") -- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") -+ # Apply to all targets; consider per-target options for finer control -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") -+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") -+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") - --Then, you can specify this toolchain file as part of your Conan profile as well: -+Then, specify this toolchain file as part of your Conan profile: - - .. code-block:: ini -- :caption: *profiles/asan_ubsan* -+ :caption: profiles/asan_ubsan - -- include(default) -+ include(default) - -- [settings] -- compiler.sanitizer=AddressUndefinedBehavior -+ [settings] -+ build_type=Debug -+ compiler.sanitizer=AddressUndefinedBehavior - -- [conf] -- tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake -+ [conf] -+ tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake - - This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. - --Managing Sanitizer with Conan Hooks --################################### -+Managing sanitizers with Conan hooks -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - --Another approach to manage sanitizers is by using :ref:`Conan hooks `. --Using hooks, you can inject compiler flags on-the-fly during the build process, --allowing for more dynamic configurations without modifying the original build files. -+Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler -+flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original -+build files. - --For instance, we can add a ``pre_build`` hook to append the necessary sanitizer flags based on the --``compiler.sanitizer`` setting. -+For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the -+``compiler.sanitizer`` setting: - - .. code-block:: python -- :caption: ~/.conan2/extentions/hooks/hook_sanitizer_flags.py -- -- def pre_generate(conanfile): -- if conanfile.settings.get_safe("compiler.sanitizer"): -- sanitizer = {"Address": "address", "UndefinedBehavior": "undefined"} -- if conanfile.settings.compiler.sanitizer in sanitizer: -- flag = f"-fsanitize={sanitizer[conanfile.settings.compiler.sanitizer]}" -- conanfile.conf.append("tools.build:cflags", flag) -- conanfile.conf.append("tools.build:cxxflags", flag) -- conanfile.conf.append("tools.build:exelinkflags", flag) -- --The ``pre_generate`` hook is executed before Conan generates toolchain files, being able to consume --the respective configuration for the compiler flags. This approach allows for more dynamic configurations --as it's possible to run a Python script, but it also increase the maintainance complexity as it keeps the --logic out for the profile management. -+ :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py -+ -+ def pre_generate(conanfile): -+ sani = conanfile.settings.get_safe("compiler.sanitizer") -+ if not sani or sani == "null": -+ return -+ mapping = { -+ "Address": "address", -+ "Leak": "leak", -+ "Thread": "thread", -+ "Memory": "memory", -+ "UndefinedBehavior": "undefined", -+ "HardwareAssistanceAddress": "hwaddress", -+ "KernelAddress": "kernel-address", -+ "AddressUndefinedBehavior": "address,undefined", -+ "ThreadUndefinedBehavior": "thread,undefined", -+ } -+ fs = mapping.get(sani) -+ if not fs: -+ return -+ flag = f"-fsanitize={fs}" -+ for k in ("tools.build:cflags", "tools.build:cxxflags", -+ "tools.build:exelinkflags", "tools.build:sharedlinkflags"): -+ conanfile.conf.append(k, flag) -+ # Optional: better stack traces -+ conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") -+ -+The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final -+configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity -+as it moves logic out of profile management. -+ -+Additional recommendations -+-------------------------- -+ -+* Debug info and optimization: -+ -+ * For ASan/TSan, ``-O1`` or ``-O2`` generally works; for MSan, prefer ``-O1`` and avoid aggressive inlining. -+ * ``-fno-omit-frame-pointer`` helps stack traces. -+ -+* Runtime symbolization: -+ -+ * Useful settings for CI: -+ -+ * ``ASAN_OPTIONS=halt_on_error=1:detect_leaks=1:log_path=asan``. -+ * ``UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:log_path=ubsan``. -+ -+* Suppressions: -+ -+ * For ASan: ``ASAN_OPTIONS=suppressions=asan.supp``. -+ * For UBSan: ``UBSAN_OPTIONS=suppressions=ubsan.supp``. -+ * Keep suppressions under version control and load them in CI jobs. -+ -+* Third-party dependencies: -+ -+ * Mixed instrumented/uninstrumented code can lead to false positives or crashes, especially with MSan. -+ * Prefer building dependencies with the same sanitizer or limit sanitizers to leaf applications. -+ -+* MSVC and Windows notes: -+ -+ * ASan with MSVC/Clang-cl uses ``/fsanitize=address`` and PDBs via ``/Zi``. Not supported for 32-bit targets. -+ * KAsan requires Windows 11. -+ * Some features are limited when using whole program optimization (``/GL``) or certain runtime libraries. --- -2.51.0 - - -From 2abb246d9d6ff96331b3f31fb27fcf92433bfd35 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Wed, 1 Oct 2025 12:49:19 +0200 -Subject: [PATCH 07/11] Remove unsed header. - -Co-authored-by: Carlos Zoido -Signed-off-by: Uilian Ries ---- - examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 14a582d6a0c0f04a82c57b6e80150f4c616955f9..c1e4513feefbf3472cb740f35fa8635486b8953c 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -1,5 +1,3 @@ --### Compiler sanitizers -- - .. _examples_dev_flow_sanitizers_compiler_sanitizers: - - Compiler sanitizers --- -2.51.0 - - -From 19954284cdc49241647ef737bca92f828a6e34c0 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Wed, 1 Oct 2025 13:49:15 +0200 -Subject: [PATCH 08/11] Update sanitizers warning - -Signed-off-by: Uilian Ries ---- - examples/dev_flow/sanitizers/compiler_sanitizers.rst | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index c1e4513feefbf3472cb740f35fa8635486b8953c..5aca1a985a3a30211480c436c146e3fb24332fc1 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -5,7 +5,9 @@ Compiler sanitizers - - .. warning:: - -- Using sanitizers in production, particularly with SUID binaries, is dangerous. The libsanitizer -+ Using sanitizers in production, especially with programs that run with elevated privileges (for example, SUID binaries on Linux), is dangerous. -+ The sanitizer runtime libraries depend on environment variables, which could allow privilege escalation attacks. -+ Use sanitizers only in development and testing environments. - runtimes rely on environment variables that could enable privilege escalation attacks. - Use sanitizers only in development and testing environments. - --- -2.51.0 - - -From 4a7bef9163f828c1a4203a201d77f4445cf2cdff Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Wed, 1 Oct 2025 13:50:13 +0200 -Subject: [PATCH 09/11] Improve document description - -Co-authored-by: Carlos Zoido -Signed-off-by: Uilian Ries ---- - examples/dev_flow/sanitizers/compiler_sanitizers.rst | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 5aca1a985a3a30211480c436c146e3fb24332fc1..45afba9d54e0af72e652aff1cbe37073ce75cce3 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -15,7 +15,7 @@ Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, - dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as - GCC, Clang, and MSVC support these tools through specific compiler and linker flags. - --This document explains recommended approaches for integrating compiler sanitizers into your Conan 2.x workflow. -+This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. - - Modeling and applying sanitizers using settings - ----------------------------------------------- --- -2.51.0 - - -From bcb5eec599d6ea83a1837903f560f9a3235af7b1 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Thu, 2 Oct 2025 08:10:00 +0200 -Subject: [PATCH 10/11] Remove Sanitizers with Conan hooks section - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 42 ------------------- - 1 file changed, 42 deletions(-) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 45afba9d54e0af72e652aff1cbe37073ce75cce3..0bdc8a9dbc75c6bc3d6393a350c195e5eeb6dac1 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -281,48 +281,6 @@ Then, specify this toolchain file as part of your Conan profile: - - This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. - --Managing sanitizers with Conan hooks --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- --Another approach is using :ref:`Conan hooks `. With hooks, you can inject compiler --flags on-the-fly during the build process, allowing for dynamic configurations without modifying the original --build files. -- --For instance, add a ``pre_generate`` hook to append the necessary sanitizer flags based on the --``compiler.sanitizer`` setting: -- --.. code-block:: python -- :caption: ~/.conan2/extensions/hooks/hook_sanitizer_flags.py -- -- def pre_generate(conanfile): -- sani = conanfile.settings.get_safe("compiler.sanitizer") -- if not sani or sani == "null": -- return -- mapping = { -- "Address": "address", -- "Leak": "leak", -- "Thread": "thread", -- "Memory": "memory", -- "UndefinedBehavior": "undefined", -- "HardwareAssistanceAddress": "hwaddress", -- "KernelAddress": "kernel-address", -- "AddressUndefinedBehavior": "address,undefined", -- "ThreadUndefinedBehavior": "thread,undefined", -- } -- fs = mapping.get(sani) -- if not fs: -- return -- flag = f"-fsanitize={fs}" -- for k in ("tools.build:cflags", "tools.build:cxxflags", -- "tools.build:exelinkflags", "tools.build:sharedlinkflags"): -- conanfile.conf.append(k, flag) -- # Optional: better stack traces -- conanfile.conf.append("tools.build:cxxflags", "-fno-omit-frame-pointer") -- --The ``pre_generate`` hook is executed before Conan generates toolchain files, so it can contribute to the final --configuration for compiler and linker flags. This approach is flexible, but can increase maintenance complexity --as it moves logic out of profile management. -- - Additional recommendations - -------------------------- - --- -2.51.0 - - -From 607a8f206a3fd3bebb6b49aa133f11dbf0a97ba5 Mon Sep 17 00:00:00 2001 -From: Uilian Ries -Date: Thu, 2 Oct 2025 08:36:41 +0200 -Subject: [PATCH 11/11] Add tables - -Signed-off-by: Uilian Ries ---- - .../sanitizers/compiler_sanitizers.rst | 60 +++++++++++++++++++ - 1 file changed, 60 insertions(+) - -diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -index 0bdc8a9dbc75c6bc3d6393a350c195e5eeb6dac1..cb7fcc47c56e71c0a1178e5235ccf5943ae581da 100644 ---- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst -+++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst -@@ -15,6 +15,34 @@ Sanitizers are powerful tools for detecting runtime bugs like buffer overflows, - dangling pointers, use-of-uninitialized memory, and various types of undefined behavior. Compilers such as - GCC, Clang, and MSVC support these tools through specific compiler and linker flags. - -+Compiler Sanitizer Support Comparison -+------------------------------------- -+ -+The following table summarizes the support for various sanitizers across different compilers: -+ -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| Sanitizer | GCC | Clang | MSVC | Notes | -++========================================+=====+=======+======+=========================================+ -+| **AddressSanitizer (ASan)** | ✅ | ✅ | ✅ | MSVC: Not supported for 32-bit targets | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **ThreadSanitizer (TSan)** | ✅ | ✅ | ❌ | Detects data races | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **MemorySanitizer (MSan)** | ❌ | ✅ | ❌ | Clang-only, requires `-O1` | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **UndefinedBehaviorSanitizer (UBSan)** | ✅ | ✅ | ❌ | Wide range of undefined behavior checks | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **LeakSanitizer (LSan)** | ✅ | ✅ | ❌ | Often integrated with ASan | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **HardwareAddressSanitizer (HWASan)** | ❌ | ✅ | ❌ | ARM64 only, lower overhead than ASan | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **KernelAddressSanitizer (KASan)** | ✅ | ✅ | ✅ | MSVC: Requires Windows 11 | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **DataFlowSanitizer (DFSan)** | ❌ | ✅ | ❌ | Dynamic data flow analysis | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+| **Control Flow Integrity (CFI)** | ❌ | ✅ | ✅ | MSVC: `/guard:cf` | -++----------------------------------------+-----+-------+------+-----------------------------------------+ -+ -+ - This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. - - Modeling and applying sanitizers using settings -@@ -56,6 +84,38 @@ The ``null`` value represents a build without sanitizers. The above models the u - ``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, - ``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. - -+Common Sanitizer Combinations -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -++-------------------+-----+-------+------+-----------------------------------------+ -+| Combination | GCC | Clang | MSVC | Compatibility | -++===================+=====+=======+======+=========================================+ -+| **ASan + UBSan** | ✅ | ✅ | ❌ | Most common combination | -++-------------------+-----+-------+------+-----------------------------------------+ -+| **TSan + UBSan** | ✅ | ✅ | ❌ | Good for multithreaded code | -++-------------------+-----+-------+------+-----------------------------------------+ -+| **ASan + LSan** | ✅ | ✅ | ❌ | LSan often enabled by default with ASan | -++-------------------+-----+-------+------+-----------------------------------------+ -+| **MSan + UBSan** | ❌ | ✅ | ❌ | Requires careful dependency management | -++-------------------+-----+-------+------+-----------------------------------------+ -+ -+Compiler-Specific Flags -+^^^^^^^^^^^^^^^^^^^^^^^ -+ -++-----------------------+------------------------+------------------------+----------------------+ -+| Sanitizer | GCC Flag | Clang Flag | MSVC Flag | -++=======================+========================+========================+======================+ -+| **AddressSanitizer** | `-fsanitize=address` | `-fsanitize=address` | `/fsanitize=address` | -++-----------------------+------------------------+------------------------+----------------------+ -+| **ThreadSanitizer** | `-fsanitize=thread` | `-fsanitize=thread` | N/A | -++-----------------------+------------------------+------------------------+----------------------+ -+| **MemorySanitizer** | N/A | `-fsanitize=memory` | N/A | -++-----------------------+------------------------+------------------------+----------------------+ -+| **UndefinedBehavior** | `-fsanitize=undefined` | `-fsanitize=undefined` | N/A | -++-----------------------+------------------------+------------------------+----------------------+ -+| **LeakSanitizer** | `-fsanitize=leak` | `-fsanitize=leak` | N/A | -++-----------------------+------------------------+------------------------+----------------------+ -+ - It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, - refer to: - --- -2.51.0 +.. _examples_dev_flow_sanitizers_compiler_sanitizers: + +Compiler sanitizers +=================== + +.. warning:: + + Do not use sanitizers for production builds, especially for binaries with elevated privileges (e.g., SUID). + Sanitizer runtimes rely on environment variables and can enable privilege escalation. + Use only in development and testing. + +Sanitizers are powerful runtime instrumentation tools that detect issues such as: + +* Buffer overflows (stack/heap), use-after-free, double-free +* Data races in multithreaded code +* Memory leaks +* Use of uninitialized memory +* A wide range of undefined behaviors + +Compilers such as GCC, Clang, and MSVC support sanitizers via compiler and linker flags. + +This page explains recommended approaches for integrating compiler sanitizers into your workflow with Conan. + +Compiler Sanitizer Support Comparison +------------------------------------- + +.. important:: + + Always rebuild all dependencies from source when enabling sanitizers to ensure consistent instrumentation + and to avoid false positives (particularly critical for MemorySanitizer). + +Each compiler has different levels of support for various sanitizers, Clang being the most comprehensive so far. +To help you choose the right sanitizer for your needs and compiler, here is a summary of the most common ones: + ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| Sanitizer | GCC | Clang | MSVC | Notes | ++========================================+=====+=======+======+=========================================+ +| **AddressSanitizer (ASan)** | ✅ | ✅ | ✅ | MSVC: Not supported for 32-bit targets | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **ThreadSanitizer (TSan)** | ✅ | ✅ | ❌ | Detects data races | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **MemorySanitizer (MSan)** | ❌ | ✅ | ❌ | Clang-only, requires `-O1` | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **UndefinedBehaviorSanitizer (UBSan)** | ✅ | ✅ | ❌ | Wide range of undefined behavior checks | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **LeakSanitizer (LSan)** | ✅ | ✅ | ❌ | Often integrated with ASan | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **HardwareAddressSanitizer (HWASan)** | ❌ | ✅ | ❌ | ARM64 only, lower overhead than ASan | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **KernelAddressSanitizer (KASan)** | ✅ | ✅ | ✅ | MSVC: Requires Windows 11 | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **DataFlowSanitizer (DFSan)** | ❌ | ✅ | ❌ | Dynamic data flow analysis | ++----------------------------------------+-----+-------+------+-----------------------------------------+ +| **Control Flow Integrity (CFI)** | ❌ | ✅ | ✅ | MSVC: `/guard:cf` | ++----------------------------------------+-----+-------+------+-----------------------------------------+ + +Besides MSVC having more limited support for sanitizers, it encourages the community to vote for new features +at `Developer Community `_. + +Also, you can consider the typical use cases for each sanitizer: + +* **AddressSanitizer (ASan)**: Great default for memory errors; often combined with UBSan for broader coverage. +* **ThreadSanitizer (TSan)**: Find data races in multithreaded code. +* **MemorySanitizer (MSan)**: Detects uninitialized memory reads (Clang-only). Requires all dependencies to be instrumented. +* **LeakSanitizer (LSan)**: Often included with ASan on Clang/GCC, can be enabled explicitly. Typically used to find memory leaks. +* **UndefinedBehaviorSanitizer (UBSan)**: Catches many undefined behaviors; often combined with ASan. +Common Sanitizer Combinations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The sanitizers can often be combined to provide more comprehensive coverage, but not all combinations are supported by every compiler. +Here are some common combinations and their compatibility mostly used with GCC and Clang: + ++-------------------+-----+-------+------+-----------------------------------------+ +| Combination | GCC | Clang | MSVC | Compatibility | ++===================+=====+=======+======+=========================================+ +| **ASan + UBSan** | ✅ | ✅ | ❌ | Most common combination | ++-------------------+-----+-------+------+-----------------------------------------+ +| **TSan + UBSan** | ✅ | ✅ | ❌ | Good for multithreaded code | ++-------------------+-----+-------+------+-----------------------------------------+ +| **ASan + LSan** | ✅ | ✅ | ❌ | LSan often enabled by default with ASan | ++-------------------+-----+-------+------+-----------------------------------------+ +| **MSan + UBSan** | ❌ | ✅ | ❌ | Requires careful dependency management | ++-------------------+-----+-------+------+-----------------------------------------+ + +**Notes on combinations**: + +* AddressSanitizer (ASan), ThreadSanitizer (TSan), and MemorySanitizer (MSan) **are mutually exclusive with one another**. +* MemorySanitizer often requires special flags such as ``-O1``, ``-fno-omit-frame-pointer`` and fully-instrumented dependencies; + mixing with non-instrumented code leads to crashes/false positives. + +Compiler-Specific Flags +^^^^^^^^^^^^^^^^^^^^^^^ + +Each compiler requires specific flags to enable the desired sanitizers. Here is a summary of the most common +sanitizers and their corresponding flags for GCC, Clang, and MSVC: + ++-----------------------+------------------------+------------------------+----------------------+ +| Sanitizer | GCC Flag | Clang Flag | MSVC Flag | ++=======================+========================+========================+======================+ +| **AddressSanitizer** | `-fsanitize=address` | `-fsanitize=address` | `/fsanitize=address` | ++-----------------------+------------------------+------------------------+----------------------+ +| **ThreadSanitizer** | `-fsanitize=thread` | `-fsanitize=thread` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **MemorySanitizer** | N/A | `-fsanitize=memory` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **UndefinedBehavior** | `-fsanitize=undefined` | `-fsanitize=undefined` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ +| **LeakSanitizer** | `-fsanitize=leak` | `-fsanitize=leak` | N/A | ++-----------------------+------------------------+------------------------+----------------------+ + +It may seem like a large number of options, but for Clang, these are only a portion. To obtain the complete list, +please refer to the official documentation for each compiler: + +* Clang: `AddressSanitizer `_, + `ThreadSanitizer `_, + `MemorySanitizer `_, + `UndefinedBehaviorSanitizer `_. +* GCC: `Instrumentation Options `_. +* MSVC: `MSVC Sanitizers `_. + +Binary Compatibility +-------------------- + +How sanitizers affect your binaries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sanitizers instrument your code at compile time, adding runtime checks and metadata. +This changes your binary's **Application Binary Interface (ABI)**, making instrumented code incompatible with non-instrumented code. + +**Key changes sanitizers make:** + +- **Memory layout**: Sanitizers add shadow memory, guard zones, or tracking metadata around your data +- **Function calls**: Standard library functions (``malloc``, ``free``, etc.) are wrapped or intercepted +- **Runtime dependencies**: Instrumented code requires sanitizer runtime libraries (``libasan``, ``libtsan``, etc.) +- **Linking**: Mixing instrumented and non-instrumented code can cause crashes, false positives, or undefined behavior + +Handling external code +^^^^^^^^^^^^^^^^^^^^^^ + +When using sanitizers, you must consider how to handle third-party dependencies. +As mixing instrumented and non-instrumented code can lead to issues, here are some strategies: + +**Always require full instrumentation:** + +- **MemorySanitizer (MSan)**: Changes function ABIs to pass shadow state. +- **DataFlowSanitizer (DFSan)**: Explicitly modifies the ABI by appending label parameters to functions. +- **ThreadSanitizer (TSan)**: Changes memory layout and intercepts synchronization primitives. + Some code may not be instrumented by ThreadSanitizer, but not recommended. + +**Usually require full instrumentation:** + +- **AddressSanitizer (ASan)**: Adds redzones and shadow memory; Works with non-instrumented code, but not recommended. +- **HardwareAddressSanitizer (HWASan)**: Similar to ASan but uses hardware tagging. Mixing is possible but not recommended. + +**Can often mix with non-instrumented code:** + +- **UndefinedBehaviorSanitizer (UBSan)**: Adds runtime checks for undefined behavior; Minimal ABI changes, safer to mix. +- **LeakSanitizer (LSan)**: Detects memory leaks at program exit; When standalone, has minimal ABI impact. + +For reliable results, **always** rebuild your entire dependency tree with the same sanitizer configuration. + +Enabling Sanitizers +------------------- + +Conan cannot infer sanitizer flags from settings automatically. +You have to pass the appropriate compiler and linker flags (e.g., ``-fsanitize=`` or ``/fsanitize=address``) via profiles or toolchains. +Conan toolchains (e.g., ``CMakeToolchain``, ``MesonToolchain``) will propagate flags defined in ``[conf]`` sections. + +Modeling and applying sanitizers using settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you want to model sanitizer options so that the package ID is affected by them, you can +:ref:`customize new compiler sub-settings `. You should not need +to modify ``settings.yml`` directly; instead add :ref:`the settings_user.yml `. + +This approach is preferred because enabling a sanitizer alters the package ID, allowing you to build and use +the same binary package with or without sanitizers. This is ideal for development and debugging workflows. + +Configuring sanitizers as part of settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you typically use a specific set of sanitizers or combinations for your builds, you can specify +a sub-setting as a list of values in your ``settings_user.yml``. For example, for Clang: + +.. code-block:: yaml + :caption: settings_user.yml + :emphasize-lines: 3 + + compiler: + clang: + sanitizer: [null, Address, Leak, Thread, Memory, UndefinedBehavior, HardwareAssistanceAddress, KernelAddress, AddressUndefinedBehavior, ThreadUndefinedBehavior] + +This example defines a few common sanitizers. You can add any sanitizer your compiler supports. +The ``null`` value represents a build without sanitizers. The above models the use of ``-fsanitize=address``, +``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, +``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. + +Adding sanitizers as part of the profile +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Another option is to add the sanitizer values as part of a profile. This way, you can easily switch between +different configurations by using dedicated profiles. + +.. code-block:: ini + :caption: compiler_sanitizers/profiles/asan + + include(default) + + [settings] + build_type=Debug + compiler.sanitizer=Address + + [conf] + tools.build:cflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address"] + tools.build:sharedlinkflags+=["-fsanitize=address"] + + [runenv] + ASAN_OPTIONS="halt_on_error=1:detect_leaks=1" + +For Visual Studio (MSVC) we can obtain an equivalent profile for AddressSanitizer: + +.. code-block:: ini + :caption: ~/.conan/profiles/asan + + include(default) + + [settings] + build_type=Debug + compiler.sanitizer=Address + + [conf] + tools.build:cxxflags+=["/fsanitize=address", "/Zi"] + tools.build:exelinkflags+=["/fsanitize=address"] + +The Conan client is not capable of deducing the necessary flags from the settings and applying them automatically +during the build process. It is necessary to pass the expected sanitizer flags according to the +``compiler.sanitizer`` value as part of the compiler and linker flags. +Conan's built-in toolchains (like ``CMakeToolchain`` and ``MesonToolchain``) will automatically +pick up the flags defined in the ``[conf]`` section and apply them to the build. + +Managing sanitizers with a CMake toolchain +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Besides using Conan profiles to manage sanitizer settings, you can also use other approaches. + +If you already have a :ref:`custom CMake toolchain file ` to manage compiler +and build options, you can pass the necessary flags to enable sanitizers there instead of profiles. + +.. code-block:: cmake + :caption: cmake/my_toolchain.cmake + + # Apply to all targets; consider per-target options for finer control + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined") + +Then, specify this toolchain file as part of your Conan profile: + +.. code-block:: ini + :caption: profiles/asan_ubsan + + include(default) + + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.cmake.cmaketoolchain:user_toolchain=cmake/my_toolchain.cmake + +This way, you can keep your existing CMake toolchain file and still leverage Conan profiles to manage other settings. + +Building Examples Using Sanitizers +---------------------------------- + +To better illustrate this, first, please clone the sources to recreate this project. You can find them in the +`examples2 repository `_ on GitHub: + +.. code-block:: bash + + git clone https://github.com/conan-io/examples2.git + cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers + +In this example we will see how to prepare Conan to use sanitizers in different ways. + +To show how to use sanitizers in your builds, let's consider two examples. + +AddressSanitizer: index out of bounds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this example, we will build a simple C++ program that intentionally accesses an out-of-bounds index +in an array, which should trigger ASan when running the program. + +.. code-block:: cpp + :caption: index_out_of_bounds/main.cpp + :emphasize-lines: 11 + + #include + #include + + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int foo[100]; + foo[100] = 42; // Out-of-bounds write + + return EXIT_SUCCESS; + } + +**Note:** The preprocessor check above is portable for GCC, Clang and MSVC. +The define ``__SANITIZE_ADDRESS__`` is present when **ASan** is active; + +**To build and run this example using Conan:** + +.. code-block:: bash + + conan export index_out_of_bounds/ + conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + # Activate run environment to ensure sanitizer runtime and paths are set + source index_out_of_bounds/install/conanrun.sh + index_out_of_bounds + +**Expected output (abbreviated):** + +.. code-block:: text + + Address sanitizer enabled + ==32018==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffbe04a6d0 ... + WRITE of size 4 at 0x7fffbe04a6d0 thread T0 + #0 ... in main .../index_out_of_bounds+0x12ea + ... + SUMMARY: AddressSanitizer: stack-buffer-overflow ... in main + This frame has 1 object(s): + [48, 448) 'foo' (line 11) <== Memory access at offset 448 overflows this variable + +UndefinedBehaviorSanitizer: signed integer overflow +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example demonstrates how to use UBSan to detect signed integer overflow. It combines ASan and UBSan. +Create a dedicated profile: + +.. code-block:: ini + :caption: ~/.conan/profiles/asan_ubsan + :emphasize-lines: 7 + + include(default) + + [settings] + build_type=Debug + compiler.sanitizer=AddressUndefinedBehavior + + [conf] + tools.build:cflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:cxxflags+=["-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + tools.build:exelinkflags+=["-fsanitize=address,undefined"] + tools.build:sharedlinkflags+=["-fsanitize=address,undefined"] + +It is supported by GCC and Clang. MSVC does not support UBSan. + +**Source code:** + +.. code-block:: cpp + :caption: signed_integer_overflow/main.cpp + :emphasize-lines: 14 + + #include + #include + #include + + int main() { + #ifdef __SANITIZE_ADDRESS__ + std::cout << "Address sanitizer enabled\n"; + #else + std::cout << "Address sanitizer not enabled\n"; + #endif + + int x = INT_MAX; + x += 42; // signed integer overflow + + return EXIT_SUCCESS; + } + +**Build and run:** + +.. code-block:: bash + + conan export signed_integer_overflow/ + conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing + source signed_integer_overflow/install/conanrun.sh + signed_integer_overflow + +**Expected output (abbreviated):** + +.. code-block:: text + + Address sanitizer enabled + .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' + +Additional recommendations +-------------------------- + +* Debug info and optimization: + + * For ASan/TSan, ``-O1`` or ``-O2`` generally works; for MSan, prefer ``-O1`` and avoid aggressive inlining. + * ``-fno-omit-frame-pointer`` helps stack traces. + +* Runtime symbolization: + + * Useful settings for CI: + + * ``ASAN_OPTIONS=halt_on_error=1:detect_leaks=1:log_path=asan``. + * ``UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:log_path=ubsan``. + +* Suppressions: + + * For ASan: ``ASAN_OPTIONS=suppressions=asan.supp``. + * For UBSan: ``UBSAN_OPTIONS=suppressions=ubsan.supp``. + * Keep suppressions under version control and load them in CI jobs. + +* Third-party dependencies: + + * Mixed instrumented/uninstrumented code can lead to false positives or crashes, especially with MSan. + * Prefer building dependencies with the same sanitizer or limit sanitizers to leaf applications. + +* MSVC and Windows notes: + + * ASan with MSVC/Clang-cl uses ``/fsanitize=address`` and PDBs via ``/Zi``. Not supported for 32-bit targets. + * KAsan requires Windows 11. + * Some features are limited when using whole program optimization (``/GL``) or certain runtime libraries. From 4311346e1eda43eee3f191b68888ca2523629503 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 11:27:57 +0200 Subject: [PATCH 27/30] Add note about having multiple sanitizers in settings Signed-off-by: Uilian Ries --- examples/dev_flow/sanitizers/compiler_sanitizers.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index c70464870385..59d77ed49fd8 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -196,6 +196,12 @@ The ``null`` value represents a build without sanitizers. The above models the u ``-fsanitize=thread``, ``-fsanitize=memory``, ``-fsanitize=leak``, ``-fsanitize=undefined``, ``-fsanitize=hwaddress``, ``-fsanitize=kernel-address``, as well as combinations like ``-fsanitize=address,undefined`` and ``-fsanitize=thread,undefined``. +As the ``sanitizer`` setting is a list, it can be choose by one single value at time. +As an workaround to support mutiple sanitizers at same time, you can define combinations like +``AddressUndefinedBehavior`` and ``ThreadUndefinedBehavior``, as listed above. +There is no limitation on the number of combinations you can define, but keep in mind that these are only tags +to help you manage your builds. You still need to pass the appropriate flags to the compiler and linker accordingly. + Adding sanitizers as part of the profile ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 81e012b86e9c0024ac0bf67da9eb1d6905ec3f93 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 11:39:00 +0200 Subject: [PATCH 28/30] Use Conan build command instead of install --build --- .../dev_flow/sanitizers/compiler_sanitizers.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/examples/dev_flow/sanitizers/compiler_sanitizers.rst index 59d77ed49fd8..24fad69de7a8 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/examples/dev_flow/sanitizers/compiler_sanitizers.rst @@ -329,10 +329,8 @@ The define ``__SANITIZE_ADDRESS__`` is present when **ASan** is active; .. code-block:: bash conan export index_out_of_bounds/ - conan install --requires=index_out_of_bounds/0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing - # Activate run environment to ensure sanitizer runtime and paths are set - source index_out_of_bounds/install/conanrun.sh - index_out_of_bounds + conan build index_out_of_bounds --version=0.1.0 -pr profiles/asan -of index_out_of_bounds/install --build=missing + index_out_of_bounds/build/Debug/index_out_of_bounds **Expected output (abbreviated):** @@ -399,9 +397,8 @@ It is supported by GCC and Clang. MSVC does not support UBSan. .. code-block:: bash conan export signed_integer_overflow/ - conan install --requires=signed_integer_overflow/0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing - source signed_integer_overflow/install/conanrun.sh - signed_integer_overflow + conan build signed_integer_overflow/ --version=0.1.0 -pr profiles/asan_ubsan -of signed_integer_overflow/install --build=missing + signed_integer_overflow/build/Debug/signed_integer_overflow **Expected output (abbreviated):** @@ -410,6 +407,8 @@ It is supported by GCC and Clang. MSVC does not support UBSan. Address sanitizer enabled .../main.cpp:16:9: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' +When executing the example application, UBSan detects the signed integer overflow and reports it as expected. + Additional recommendations -------------------------- From a1095e2c2b2cd41ac33e7a34f120be9889724c91 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 11:44:23 +0200 Subject: [PATCH 29/30] Move sanitizers page to security folder Signed-off-by: Uilian Ries --- examples/dev_flow.rst | 1 - .../compiler_sanitizers.rst => security/sanitizers.rst | 6 +++--- security/security.rst | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) rename examples/dev_flow/sanitizers/compiler_sanitizers.rst => security/sanitizers.rst (99%) diff --git a/examples/dev_flow.rst b/examples/dev_flow.rst index 21d7e0e94744..4363e2e079b5 100644 --- a/examples/dev_flow.rst +++ b/examples/dev_flow.rst @@ -8,5 +8,4 @@ Developer tools and flows dev_flow/debug/step_into_dependencies dev_flow/debug/debugging_visual - dev_flow/sanitizers/compiler_sanitizers dev_flow/tool_requires/mingw diff --git a/examples/dev_flow/sanitizers/compiler_sanitizers.rst b/security/sanitizers.rst similarity index 99% rename from examples/dev_flow/sanitizers/compiler_sanitizers.rst rename to security/sanitizers.rst index 24fad69de7a8..5ad88ad347d5 100644 --- a/examples/dev_flow/sanitizers/compiler_sanitizers.rst +++ b/security/sanitizers.rst @@ -1,7 +1,7 @@ -.. _examples_dev_flow_sanitizers_compiler_sanitizers: +.. _security_sanitizers: -Compiler sanitizers -=================== +Sanitizers +========== .. warning:: diff --git a/security/security.rst b/security/security.rst index 8c734ee18c04..1b57938a75dc 100644 --- a/security/security.rst +++ b/security/security.rst @@ -12,3 +12,4 @@ Security is a critical aspect of many software development projects and products audit sboms guidelines + sanitizers From a39cb7d667a4bf11b0b3d7571f3ac5035e62c394 Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 2 Oct 2025 11:51:19 +0200 Subject: [PATCH 30/30] Update folder name for examples Signed-off-by: Uilian Ries --- security/sanitizers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/sanitizers.rst b/security/sanitizers.rst index 5ad88ad347d5..31bd89868492 100644 --- a/security/sanitizers.rst +++ b/security/sanitizers.rst @@ -289,7 +289,7 @@ To better illustrate this, first, please clone the sources to recreate this proj .. code-block:: bash git clone https://github.com/conan-io/examples2.git - cd examples2/examples/dev_flow/sanitizers/compiler_sanitizers + cd examples2/examples/security/sanitizers/compiler_sanitizers In this example we will see how to prepare Conan to use sanitizers in different ways.