From 5eaae041e268453153037750ca127d63c19246c6 Mon Sep 17 00:00:00 2001 From: Michael D Kinney Date: Wed, 23 Oct 2024 18:43:07 -0700 Subject: [PATCH] UnitTestFrameworkPkg/UnitTestLib: Reduce sanitizer false positive Use snprintf() in host based unit tests to format log messages and add host specific wrapper for LongJump() that is decorated with NORETURN to provide hint to address sanitizer that LongJump() never returns. Signed-off-by: Michael D Kinney --- .../UnitTestDebugAssertLibHost.cpp | 24 ++++++++++++++++++- .../Library/UnitTestLib/AssertCmocka.c | 18 +++++++++----- .../Library/UnitTestLib/RunTestsCmocka.c | 12 ++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp index a4405cc205ba..ad8487ad1b6b 100644 --- a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp +++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.cpp @@ -24,6 +24,27 @@ extern "C" { /// 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. @@ -47,7 +68,8 @@ extern "C" { if (gUnitTestExpectAssertFailureJumpBuffer != NULL) { UT_LOG_INFO ("Detected expected ASSERT: %a(%d): %a\n", FileName, LineNumber, Description); - LongJump (gUnitTestExpectAssertFailureJumpBuffer, 1); + HostLongJump (gUnitTestExpectAssertFailureJumpBuffer, 1); + UNREACHABLE (); } else { if (GetActiveFrameworkHandle () != NULL) { AsciiStrCpyS (Message, sizeof (Message), "Detected unexpected ASSERT("); diff --git a/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c b/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c index 0d8e36c938aa..b681f0480ae7 100644 --- a/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c +++ b/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c @@ -381,21 +381,27 @@ UnitTestExpectAssertFailure ( } if (UnitTestStatus == UNIT_TEST_PASSED) { - UT_LOG_INFO ( - "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n", + snprintf ( + TempStr, + sizeof (TempStr), + "[ASSERT PASS] %s:%d: UT_EXPECT_ASSERT_FAILURE(%s) detected expected assert\n", FileName, - LineNumber, + (int)LineNumber, FunctionCall ); + UT_LOG_INFO (TempStr); } if (UnitTestStatus == UNIT_TEST_SKIPPED) { - UT_LOG_WARNING ( - "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n", + snprintf ( + TempStr, + sizeof (TempStr), + "[ASSERT WARN] %s:%d: UT_EXPECT_ASSERT_FAILURE(%s) disabled\n", FileName, - LineNumber, + (int)LineNumber, FunctionCall ); + UT_LOG_WARNING (TempStr); } if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) { diff --git a/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c b/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c index f24b65174c5c..5788a75b7f48 100644 --- a/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c +++ b/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c @@ -111,10 +111,14 @@ CmockaUnitTestTeardownFunctionRunner ( // stdout and stderr in their xml format // if (UnitTest->Log != NULL) { - print_message ("UnitTest: %s - %s\n", UnitTest->Name, UnitTest->Description); - print_message ("Log Output Start\n"); - print_message ("%s", UnitTest->Log); - print_message ("Log Output End\n"); + // + // UnitTest->Log can be a large buffer that is larger than what DEBUG() + // can support. Use printf() directly. + // + printf ("UnitTest: %s - %s\n", UnitTest->Name, UnitTest->Description); + printf ("Log Output Start\n"); + printf (UnitTest->Log); + printf ("Log Output End\n"); } //