https://bugzilla.tianocore.org/show_bug.cgi?id=2505 * Add unit tests for SafeIntLib class * Add unit tests for BaseLib Base64 conversion APIs. * Add Test/MdePkgHostTest.dsc -to build host based unit tests * Update MdePkg.dsc to build target based tests for SafeIntLib and BaseLib * Update MdePkg.ci.yaml to build and run host based tests for SafeIntLib and BaseLib Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Acked-by: Hao A Wu <hao.a.wu@intel.com> Reviewed-by: Bret Barkelew <Bret.Barkelew@microsoft.com>
		
			
				
	
	
		
			541 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			541 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   IA32-specific functions for unit-testing INTN and UINTN functions in
 | |
|   SafeIntLib.
 | |
| 
 | |
|   Copyright (c) Microsoft Corporation.<BR>
 | |
|   Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "TestBaseSafeIntLib.h"
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeInt32ToUintn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INT32       Operand;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is non-negative, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeInt32ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (-1537977259);
 | |
|   Status = SafeInt32ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUint32ToIntn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT32      Operand;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is <= MAX_INTN, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUint32ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0xabababab);
 | |
|   Status = SafeUint32ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeIntnToInt32 (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INTN        Operand;
 | |
|   INT32       Result;
 | |
| 
 | |
|   //
 | |
|   // INTN is same as INT32 in IA32, so this is just a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeIntnToInt32(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeIntnToUint32 (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INTN        Operand;
 | |
|   UINT32      Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is non-negative, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeIntnToUint32(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (-1537977259);
 | |
|   Status = SafeIntnToUint32(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnToUint32 (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Operand;
 | |
|   UINT32      Result;
 | |
| 
 | |
|   //
 | |
|   // UINTN is same as UINT32 in IA32, so this is just a cast
 | |
|   //
 | |
|   Operand = 0xabababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnToUint32(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0xabababab, Result);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnToIntn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Operand;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is <= MAX_INTN, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnToIntn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0xabababab);
 | |
|   Status = SafeUintnToIntn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnToInt64 (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Operand;
 | |
|   INT64       Result;
 | |
| 
 | |
|   //
 | |
|   // UINTN is same as UINT32 in IA32, and UINT32 is a subset of
 | |
|   // INT64, so this is just a cast
 | |
|   //
 | |
|   Operand = 0xabababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnToInt64(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0xabababab, Result);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeInt64ToIntn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INT64       Operand;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is between MIN_INTN and  MAX_INTN2 inclusive, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeInt64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   Operand = (-1537977259);
 | |
|   Status = SafeInt64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL((-1537977259), Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0x5babababefefefef);
 | |
|   Status = SafeInt64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   Operand =  (-6605562033422200815);
 | |
|   Status = SafeInt64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeInt64ToUintn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INT64       Operand;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is between 0 and  MAX_UINTN inclusive, then it's a cast
 | |
|   //
 | |
|   Operand = 0xabababab;
 | |
|   Result = 0;
 | |
|   Status = SafeInt64ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0xabababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0x5babababefefefef);
 | |
|   Status = SafeInt64ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   Operand =  (-6605562033422200815);
 | |
|   Status = SafeInt64ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUint64ToIntn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT64      Operand;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is <= MAX_INTN, then it's a cast
 | |
|   //
 | |
|   Operand = 0x5bababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUint64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x5bababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0xababababefefefef);
 | |
|   Status = SafeUint64ToIntn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUint64ToUintn (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT64      Operand;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If Operand is <= MAX_UINTN, then it's a cast
 | |
|   //
 | |
|   Operand = 0xabababab;
 | |
|   Result = 0;
 | |
|   Status = SafeUint64ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0xabababab, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Operand = (0xababababefefefef);
 | |
|   Status = SafeUint64ToUintn(Operand, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnAdd (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Augend;
 | |
|   UINTN       Addend;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If the result of addition doesn't overflow MAX_UINTN, then it's addition
 | |
|   //
 | |
|   Augend = 0x3a3a3a3a;
 | |
|   Addend = 0x3a3a3a3a;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x74747474, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Augend = 0xabababab;
 | |
|   Addend = 0xbcbcbcbc;
 | |
|   Status = SafeUintnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeIntnAdd (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INTN        Augend;
 | |
|   INTN        Addend;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If the result of addition doesn't overflow MAX_INTN
 | |
|   // and doesn't underflow MIN_INTN, then it's addition
 | |
|   //
 | |
|   Augend = 0x3a3a3a3a;
 | |
|   Addend = 0x3a3a3a3a;
 | |
|   Result = 0;
 | |
|   Status = SafeIntnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x74747474, Result);
 | |
| 
 | |
|   Augend = (-976894522);
 | |
|   Addend = (-976894522);
 | |
|   Status = SafeIntnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL((-1953789044), Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Augend = 0x5a5a5a5a;
 | |
|   Addend = 0x5a5a5a5a;
 | |
|   Status = SafeIntnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   Augend = (-1515870810);
 | |
|   Addend = (-1515870810);
 | |
|   Status = SafeIntnAdd(Augend, Addend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnSub (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Minuend;
 | |
|   UINTN       Subtrahend;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If Minuend >= Subtrahend, then it's subtraction
 | |
|   //
 | |
|   Minuend = 0x5a5a5a5a;
 | |
|   Subtrahend = 0x3b3b3b3b;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x1f1f1f1f, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Minuend = 0x5a5a5a5a;
 | |
|   Subtrahend = 0x6d6d6d6d;
 | |
|   Status = SafeUintnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeIntnSub (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INTN        Minuend;
 | |
|   INTN        Subtrahend;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If the result of subtractions doesn't overflow MAX_INTN or
 | |
|   // underflow MIN_INTN, then it's subtraction
 | |
|   //
 | |
|   Minuend = 0x5a5a5a5a;
 | |
|   Subtrahend = 0x3a3a3a3a;
 | |
|   Result = 0;
 | |
|   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x20202020, Result);
 | |
| 
 | |
|   Minuend = 0x3a3a3a3a;
 | |
|   Subtrahend = 0x5a5a5a5a;
 | |
|   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL((-538976288), Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Minuend = (-2054847098);
 | |
|   Subtrahend = 2054847098;
 | |
|   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   Minuend = (2054847098);
 | |
|   Subtrahend = (-2054847098);
 | |
|   Status = SafeIntnSub(Minuend, Subtrahend, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeUintnMult (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Multiplicand;
 | |
|   UINTN       Multiplier;
 | |
|   UINTN       Result;
 | |
| 
 | |
|   //
 | |
|   // If the result of multiplication doesn't overflow MAX_UINTN, it will succeed
 | |
|   //
 | |
|   Multiplicand = 0xa122a;
 | |
|   Multiplier = 0xd23;
 | |
|   Result = 0;
 | |
|   Status = SafeUintnMult(Multiplicand, Multiplier, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x844c9dbe, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Multiplicand = 0xa122a;
 | |
|   Multiplier = 0xed23;
 | |
|   Status = SafeUintnMult(Multiplicand, Multiplier, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 | |
| 
 | |
| UNIT_TEST_STATUS
 | |
| EFIAPI
 | |
| TestSafeIntnMult (
 | |
|   IN UNIT_TEST_CONTEXT           Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   INTN        Multiplicand;
 | |
|   INTN        Multiplier;
 | |
|   INTN        Result;
 | |
| 
 | |
|   //
 | |
|   // If the result of multiplication doesn't overflow MAX_INTN and doesn't
 | |
|   // underflow MIN_UINTN, it will succeed
 | |
|   //
 | |
|   Multiplicand = 0x123456;
 | |
|   Multiplier = 0x678;
 | |
|   Result = 0;
 | |
|   Status = SafeIntnMult(Multiplicand, Multiplier, &Result);
 | |
|   UT_ASSERT_NOT_EFI_ERROR(Status);
 | |
|   UT_ASSERT_EQUAL(0x75c28c50, Result);
 | |
| 
 | |
|   //
 | |
|   // Otherwise should result in an error status
 | |
|   //
 | |
|   Multiplicand = 0x123456;
 | |
|   Multiplier = 0xabc;
 | |
|   Status = SafeIntnMult(Multiplicand, Multiplier, &Result);
 | |
|   UT_ASSERT_EQUAL(RETURN_BUFFER_TOO_SMALL, Status);
 | |
| 
 | |
|   return UNIT_TEST_PASSED;
 | |
| }
 |