From 2cb8bf6c69cf78db73c6a31c0b6049741c1ea006 Mon Sep 17 00:00:00 2001 From: Michael D Kinney Date: Tue, 28 Jan 2025 18:03:31 -0800 Subject: UnitTestFrameworkPkg: Fix false positives from address sanitizer PR #6408 introduced a host specific NORETURN function to resolve false positives from the address sanitizer when LongJump() is called and the stack is reset to a previous stack frame. This approach was discussed here: https://github.com/tianocore/edk2/pull/6408/files#r1918810499 False positives are still being observed with this initial solution. The address sanitizer provides __asan_handle_no_return() to clean up shadow memory before a NORETURN function is called and provides a simpler implementation for this issue without having to introduce a host specific NORETURN function. https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/sanitizer/asan_interface.h Signed-off-by: Michael D Kinney --- .../UnitTestDebugAssertLibHost.cpp | 46 +++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp index ad8487ad1b..8ed7c0988c 100644 --- a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp +++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp @@ -18,33 +18,23 @@ extern "C" { #include #include + // + // If address sanitizer is enabled, then declare the function that is used to + // handle custom long jump implementation. + // + #ifdef __SANITIZE_ADDRESS__ + void + __asan_handle_no_return ( + ); + + #endif + /// /// Point to jump buffer used with SetJump()/LongJump() to test if a function /// under test generates an expected ASSERT() condition. /// BASE_LIBRARY_JUMP_BUFFER *gUnitTestExpectAssertFailureJumpBuffer = NULL; - /** - LongJump wrapper for host-based unit test environments that is declared - NORETURN to avoid false positives from address sanitizer. - - @param JumpBuffer A pointer to CPU context buffer. - @param Value The value to return when the SetJump() context is - restored and must be non-zero. - **/ - static - VOID - NORETURN - EFIAPI - HostLongJump ( - IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, - IN UINTN Value - ) - { - LongJump (JumpBuffer, Value); - UNREACHABLE (); - } - /** Unit test library replacement for DebugAssert() in DebugLib. @@ -68,8 +58,18 @@ extern "C" { if (gUnitTestExpectAssertFailureJumpBuffer != NULL) { UT_LOG_INFO ("Detected expected ASSERT: %a(%d): %a\n", FileName, LineNumber, Description); - HostLongJump (gUnitTestExpectAssertFailureJumpBuffer, 1); - UNREACHABLE (); + + // + // If address sanitizer is enabled, then inform sanitizer that a no return + // function is being called that will reset to a previous stack frame. + // This is required to avoid false positives from the address sanitizer + // due to the use of a custom long jump implementation. + // + #ifdef __SANITIZE_ADDRESS__ + __asan_handle_no_return (); + #endif + + LongJump (gUnitTestExpectAssertFailureJumpBuffer, 1); } else { if (GetActiveFrameworkHandle () != NULL) { AsciiStrCpyS (Message, sizeof (Message), "Detected unexpected ASSERT("); -- cgit