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);