4.3.6 Returning Pointers in a Function Parameter

The following example shows a bad example for casting pointers. The function MyFunction() returns a 64-bit value in an OUT parameter that is assigned from a 32-bit input parameter. There is nothing wrong with MyFunction(). The problem is when MyFunction() is called. Here, the address of B, a 32-bit container, is cast to a pointer to a 64-bit container and passed to MyFunction(). MyFunction() writes to 64 bits starting at B. This location happens to overwrite the value of B and the value of A in the calling function.

The first Print() correctly shows the values of A and B. The second Print() shows that B was given A's original value, but the contents of A were destroyed and overwritten with a 0.

The cast from &B to a (UINT64 *) is the problem here. This code compiles without errors or warnings on both 32-bit and 64-bit processors. It executes on 32-bit and 64-bit processors with these unexpected side effects. It might also generate an alignment fault on IPF if &B is not 64-bit aligned. One possible fix for this issue is to change B from a UINT32 to a UINT64.

Example 12-Casting OUT function parameters
EFI_STATUS 
EFIAPI
MyFunction (
  IN  UINT32  ValueU32,
  OUT UINT64  *ValueU64
  )
{
  *ValueU64 = (UINT64)ValueU32;
  return EFI_SUCCESS;
}
UINT32 A;
UINT32 B;

A = 0x11112222;
B = 0x33334444;

//
// Prints "A = 11112222 B = 33334444"
//
Print (L"A = %08x B = %08x\n", A, B);

MyFunction (A, (UINT64 *)(&B));

//
// Prints "A = 00000000 B = 11112222"
//
Print (L"A = %08x B = %08x\n", A, B);