Trigger a test failure when UBSAN (-fsanitize=undefined) finds undefined behaviour

1.2k views Asked by At

I have a small unit test here which has undefined behaviour.

Source code:

#include <gtest/gtest.h>

TEST(test, test)
{
    int k = 0x7fffffff;
    k += 1; // cause integer overflow
}

GTEST_API_ int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

I enable UBSAN in my CMakeLists.txt:

cmake_minimum_required (VERSION 3.12)
project(ub CXX)

find_package(GTest REQUIRED)

add_executable        (ub_test ub_test.cpp)
target_link_libraries (ub_test GTest::GTest)
target_compile_options(ub_test PRIVATE -fsanitize=undefined)
target_link_options   (ub_test PRIVATE -fsanitize=undefined)

UBSAN correctly identifies the undefined behaviour:

/home/steve/src/ub/ub_test.cpp:6:7: runtime error: signed integer overflow:
2147483647 + 1 cannot be represented in type 'int'

However, my test still passes.

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from test
[ RUN      ] test.test
/home/steve/src/ub/ub_test.cpp:6:7: runtime error: signed integer overflow:
2147483647 + 1 cannot be represented in type 'int'
[       OK ] test.test (0 ms)
[----------] 1 test from test (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

Is it possible to trigger a test failure (throw an exception, exit 1, etc) when UBSAN finds an issue?

2

There are 2 answers

2
mediocrevegetable1 On BEST ANSWER

According to the documentation:

  • -fsanitize=...: print a verbose error report and continue execution (default);

  • -fno-sanitize-recover=...: print a verbose error report and exit the program;

  • -fsanitize-trap=...: execute a trap instruction (doesn’t require UBSan run-time support).

Note that the trap / recover options do not enable the corresponding sanitizer, and in general need to be accompanied by a suitable -fsanitize= flag.

It seems like when you use -fsanitize= the exact same thing happens which you're talking about. It notices the undefined behavior and reports it, but continues execution. So appending a -fno-sanitize-recover=all should exit the program.

0
Alexey Chernyshov On

You can try UBSAN_OPTIONS="halt_on_error=1" environment variable.

UBSAN_OPTIONS="halt_on_error=1" cmake --build cmake-build-UBSAN --target test