summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael D Kinney <michael.d.kinney@intel.com>2024-10-22 17:01:22 -0700
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-01-21 05:02:38 +0000
commit1c73f0e71dea4adc2da75b5eaf970e80c938a51e (patch)
tree2d6672022f4212a839b3e37c8dbf511f70b0fe1d
parentde06288019e62ee563d6958fb0fb7d0ffb8a2e62 (diff)
downloadedk2-1c73f0e71dea4adc2da75b5eaf970e80c938a51e.tar.gz
UnitTestFrameworkPkg: Add failing unit tests cases for sanitizer
Add GoogleTest and Framework based unit tests that are expected to fail and be caught by Address Sanitizer. These unit tests verify that an address sanitizer is enabled and detecting the following conditions. It also provide examples of the expected output when an Address Sanitizer detected these types of issues. * double free * buffer overflow * buffer underflow * null ptr * invalid address * divide by zero Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
-rw-r--r--UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp139
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.c117
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf32
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.c117
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf32
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.c117
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf32
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.c110
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf31
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.c110
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf31
-rw-r--r--UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTestExpectFail.dsc16
-rw-r--r--UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml7
13 files changed, 889 insertions, 2 deletions
diff --git a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
index 2c2765e1e5..9164f66da3 100644
--- a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
+++ b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
@@ -12,6 +12,7 @@ extern "C" {
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
+ #include <Library/MemoryAllocationLib.h>
}
/**
@@ -294,6 +295,144 @@ TEST (MacroTestsMessages, MacroTraceMessage) {
ASSERT_TRUE (TRUE);
}
+/**
+ Sample unit test that performs double free
+**/
+TEST (SanitizerTests, DoubleFreeDeathTest) {
+ UINT8 *Pointer;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ ASSERT_NE (Pointer, (UINT8 *)NULL);
+ FreePool (Pointer);
+ //
+ // Second free that should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (FreePool (Pointer), "ERROR: AddressSanitizer: heap-use-after-free");
+}
+
+/**
+ Sample unit test that performs read past end of allocated buffer
+**/
+TEST (SanitizerTests, BufferOverflowReadDeathTest) {
+ UINT8 *Pointer;
+ UINT8 Value;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ ASSERT_NE (Pointer, (UINT8 *)NULL);
+
+ //
+ // Read past end of allocated buffer that should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (Value = Pointer[110], "ERROR: AddressSanitizer: heap-buffer-overflow");
+ ASSERT_EQ (Value, Value);
+
+ FreePool (Pointer);
+}
+
+/**
+ Sample unit test that performs write past end of allocated buffer
+**/
+TEST (SanitizerTests, BufferOverflowWriteDeathTest) {
+ UINT8 *Pointer;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ ASSERT_NE (Pointer, (UINT8 *)NULL);
+
+ //
+ // Write past end of allocated buffer that should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (Pointer[110] = 0, "ERROR: AddressSanitizer: heap-buffer-overflow");
+
+ FreePool (Pointer);
+}
+
+/**
+ Sample unit test that performs read before beginning of allocated buffer
+**/
+TEST (SanitizerTests, BufferUnderflowReadDeathTest) {
+ UINT8 *Pointer;
+ UINT8 Value;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ ASSERT_NE (Pointer, (UINT8 *)NULL);
+
+ //
+ // Read past end of allocated buffer that should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (Value = Pointer[-10], "ERROR: AddressSanitizer: heap-buffer-overflow");
+ ASSERT_EQ (Value, Value);
+
+ FreePool (Pointer);
+}
+
+/**
+ Sample unit test that performs read from address 0 (NULL)
+**/
+TEST (SanitizerTests, NullPointerReadDeathTest) {
+ UINT8 Value;
+
+ //
+ // Read from address 0 should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (Value = *(volatile UINT8 *)(NULL), "ERROR: AddressSanitizer: ");
+ ASSERT_EQ (Value, Value);
+}
+
+/**
+ Sample unit test that performs write to address 0 (NULL)
+**/
+TEST (SanitizerTests, NullPointerWriteDeathTest) {
+ //
+ // Write to address 0 should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (*(volatile UINT8 *)(NULL) = 0, "ERROR: AddressSanitizer: ");
+}
+
+/**
+ Sample unit test that performs read from invalid address -1
+**/
+TEST (SanitizerTests, InvalidPointerReadDeathTest) {
+ UINT8 Value;
+
+ //
+ // Read from address -1 should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (Value = *(volatile UINT8 *)(-1), "ERROR: AddressSanitizer: ");
+ ASSERT_EQ (Value, Value);
+}
+
+/**
+ Sample unit test that performs write to invalid address -1
+**/
+TEST (SanitizerTests, InvalidPointerWriteDeathTest) {
+ //
+ // Write to address -1 should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (*(volatile UINT8 *)(-1) = 0, "ERROR: AddressSanitizer: ");
+}
+
+UINTN
+DivideWithNoParameterChecking (
+ UINTN Dividend,
+ UINTN Divisor
+ )
+{
+ //
+ // Perform integer division with no check for divide by zero
+ //
+ return (Dividend / Divisor);
+}
+
+/**
+ Sample unit test that performs a divide by 0
+**/
+TEST (SanitizerTests, DivideByZeroDeathTest) {
+ //
+ // Divide by 0 should be caught by address sanitizer, log details, and exit
+ //
+ EXPECT_DEATH (DivideWithNoParameterChecking (10, 0), "ERROR: AddressSanitizer: ");
+}
+
int
main (
int argc,
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.c b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.c
new file mode 100644
index 0000000000..1244854e41
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.c
@@ -0,0 +1,117 @@
+/** @file
+ Sample UnitTest built for execution on a Host machine.
+ This test case generates a buffer overflow that is caught by a sanitizer.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define UNIT_TEST_NAME "Sample Unit Test Sanitize Buffer Overflow"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Sample unit test the performs a buffer overflow
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SanitizeBufferOverflow (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 *Pointer;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ UT_ASSERT_NOT_NULL (Pointer);
+ Pointer[110] = 0;
+ FreePool (Pointer);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE SanitizeTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&SanitizeTests, Framework, "Sanitize tests", "Sanitize tests", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for SanitizeTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ AddTestCase (SanitizeTests, "Sanitize Buffer Overflow", "SanitizeBufferOverflow", SanitizeBufferOverflow, NULL, NULL, NULL);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf
new file mode 100644
index 0000000000..7f4c8aedf9
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf
@@ -0,0 +1,32 @@
+## @file
+# Sample UnitTest built for execution on a Host machine.
+# This test case generates a buffer overflow that is caught by a sanitizer.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SampleUnitTestBufferOverflow
+ FILE_GUID = 3772390C-CF33-4826-BB2F-A279C1AC12E0
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SampleUnitTestBufferOverflow.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UnitTestLib
+ MemoryAllocationLib
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.c b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.c
new file mode 100644
index 0000000000..3159af439e
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.c
@@ -0,0 +1,117 @@
+/** @file
+ Sample UnitTest built for execution on a Host machine.
+ This test case generates a buffer underflow that is caught by a sanitizer.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define UNIT_TEST_NAME "Sample Unit Test Sanitize Buffer Underflow"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Sample unit test the performs a buffer underflow
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SanitizeBufferUnderflow (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 *Pointer;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ UT_ASSERT_NOT_NULL (Pointer);
+ Pointer[-10] = 0;
+ FreePool (Pointer);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE SanitizeTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&SanitizeTests, Framework, "Sanitize tests", "Sanitize tests", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for SanitizeTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ AddTestCase (SanitizeTests, "Sanitize Buffer Underflow", "SanitizeBufferUnderflow", SanitizeBufferUnderflow, NULL, NULL, NULL);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf
new file mode 100644
index 0000000000..eccff61dfd
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf
@@ -0,0 +1,32 @@
+## @file
+# Sample UnitTest built for execution on a Host machine.
+# This test case generates a buffer underflow that is caught by a sanitizer.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SampleUnitTestBufferUnderflow
+ FILE_GUID = ECA331D2-D794-4798-B145-770A570F3309
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SampleUnitTestBufferUnderflow.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UnitTestLib
+ MemoryAllocationLib
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.c b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.c
new file mode 100644
index 0000000000..8c635e8a16
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.c
@@ -0,0 +1,117 @@
+/** @file
+ Sample UnitTest built for execution on a Host machine.
+ This test case generates a double free that is caught by a sanitizer.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define UNIT_TEST_NAME "Sample Unit Test Sanitize Double Free"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Sample unit test the performs a double free
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SanitizeDoubleFree (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 *Pointer;
+
+ Pointer = (UINT8 *)AllocatePool (100);
+ UT_ASSERT_NOT_NULL (Pointer);
+ FreePool (Pointer);
+ FreePool (Pointer);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE SanitizeTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&SanitizeTests, Framework, "Sanitize tests", "Sanitize tests", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for SanitizeTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ AddTestCase (SanitizeTests, "Sanitize Double Free", "SanitizeDoubleFree", SanitizeDoubleFree, NULL, NULL, NULL);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf
new file mode 100644
index 0000000000..9903a82886
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf
@@ -0,0 +1,32 @@
+## @file
+# Sample UnitTest built for execution on a Host machine.
+# This test case generates a double free that is caught by a sanitizer.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SampleUnitTestDoubleFree
+ FILE_GUID = B40BBE1C-90AB-4DE9-9B49-E734666FF9A7
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SampleUnitTestDoubleFree.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UnitTestLib
+ MemoryAllocationLib
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.c b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.c
new file mode 100644
index 0000000000..bb4e5bcd2f
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.c
@@ -0,0 +1,110 @@
+/** @file
+ Sample UnitTest built for execution on a Host machine.
+ This test case accesses an invalid address that is caught by a sanitizer.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+
+#define UNIT_TEST_NAME "Sample Unit Test Sanitize Invalid Address"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Sample unit test that accesses an invalid address
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SanitizeInvalidAddress (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ *(volatile UINT8 *)(-1) = 0;
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE SanitizeTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&SanitizeTests, Framework, "Sanitize tests", "Sanitize tests", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for SanitizeTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ AddTestCase (SanitizeTests, "Sanitize Invalid Address", "SanitizeInvalidAddress", SanitizeInvalidAddress, NULL, NULL, NULL);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf
new file mode 100644
index 0000000000..1804f28641
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf
@@ -0,0 +1,31 @@
+## @file
+# Sample UnitTest built for execution on a Host machine.
+# This test case accesses an invalid address that is caught by a sanitizer.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SampleUnitTestInvalidAddress
+ FILE_GUID = 60CED393-1342-45E9-9D8B-589F02255674
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SampleUnitTestInvalidAddress.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UnitTestLib
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.c b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.c
new file mode 100644
index 0000000000..c7e9028aaa
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.c
@@ -0,0 +1,110 @@
+/** @file
+ Sample UnitTest built for execution on a Host machine.
+ This test case dereferences a NULL pointer that is caught by a sanitizer.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+
+#define UNIT_TEST_NAME "Sample Unit Test Sanitize NULL Pointer"
+#define UNIT_TEST_VERSION "0.1"
+
+/**
+ Sample unit test that dereferences a NULL pointer.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SanitizeNullAddress (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ *(volatile UINT8 *)(NULL) = 0;
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE SanitizeTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&SanitizeTests, Framework, "Sanitize tests", "Sanitize tests", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for SanitizeTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ AddTestCase (SanitizeTests, "Sanitize NULL Address", "SanitizeNullAddress", SanitizeNullAddress, NULL, NULL, NULL);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf
new file mode 100644
index 0000000000..0b7e8af3ce
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf
@@ -0,0 +1,31 @@
+## @file
+# Sample UnitTest built for execution on a Host machine.
+# This test case dereferences a NULL pointer that is caught by a sanitizer.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SampleUnitTestNullAddress
+ FILE_GUID = FDD2EFA0-74BE-4628-A860-A60EF81B9023
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SampleUnitTestNullAddress.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UnitTestLib
diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTestExpectFail.dsc b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTestExpectFail.dsc
index face95d6c2..73b4cb1b92 100644
--- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTestExpectFail.dsc
+++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTestExpectFail.dsc
@@ -1,8 +1,13 @@
## @file
-# UnitTestFrameworkPkg DSC file used to build host-based unit tests that archive
+# UnitTestFrameworkPkg DSC file used to build host-based unit tests that are
# always expected to fail to demonstrate the format of the log file and reports
# when failures occur.
#
+# For Google Test based unit tests, in order to see full log of errors from the
+# sanitizer, the Google Test handling of exceptions must be disabled by either
+# setting the environment variable GTEST_CATCH_EXCEPTIONS=0 or passing
+# --gtest-catch-exceptions=0 on the command line when executing unit tests.
+#
# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -42,3 +47,12 @@
<BuildOptions>
MSFT:*_*_*_CC_FLAGS = /wd4723
}
+
+ #
+ # Unit tests that perform illegal actions that are caught by a sanitizer
+ #
+ UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf
+ UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf
+ UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf
+ UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf
+ UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
index c6a412c960..cf51b21e00 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
@@ -66,7 +66,12 @@
"UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTestExpectFail/SampleGoogleTestHostExpectFail.inf",
"UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTestGenerateException/SampleGoogleTestHostGenerateException.inf",
"UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestExpectFail/SampleUnitTestHostExpectFail.inf",
- "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestGenerateException/SampleUnitTestHostGenerateException.inf"
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestGenerateException/SampleUnitTestHostGenerateException.inf",
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestDoubleFree/SampleUnitTestDoubleFree.inf",
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferOverflow/SampleUnitTestBufferOverflow.inf",
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestBufferUnderflow/SampleUnitTestBufferUnderflow.inf",
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestNullAddress/SampleUnitTestNullAddress.inf",
+ "UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTestInvalidAddress/SampleUnitTestInvalidAddress.inf"
],
"DscPath": "Test/UnitTestFrameworkPkgHostTest.dsc"
},