+ } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ //\r
+ // 1. Check FileHeader.NumberOfRvaAndSizes filed.\r
+ //\r
+ if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ //\r
+ // 2. Check the FileHeader.SizeOfOptionalHeader field.\r
+ // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so\r
+ // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow.\r
+ //\r
+ HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER64) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
+ if (((UINT32)Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=\r
+ Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
+ //\r
+ // 3. Check the FileHeader.NumberOfSections field.\r
+ //\r
+ if (Hdr.Pe32Plus->OptionalHeader.SizeOfImage <= SectionHeaderOffset) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ if ((Hdr.Pe32Plus->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32Plus->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // 4. Check the OptionalHeader.SizeOfHeaders field.\r
+ //\r
+ if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders >= Hdr.Pe32Plus->OptionalHeader.SizeOfImage) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ if ((Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32Plus->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // 4.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file.\r
+ //\r
+ Size = 1;\r
+ ReadSize = Size;\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - 1,\r
+ &Size,\r
+ &BufferData\r
+ );\r
+ if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+ if (Size != ReadSize) {\r
+ Status = RETURN_UNSUPPORTED;\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check the EFI_IMAGE_DIRECTORY_ENTRY_SECURITY data.\r
+ // Read the last byte to make sure the data is in the image region.\r
+ // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.\r
+ //\r
+ if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {\r
+ if (Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) {\r
+ //\r
+ // Check the member data to avoid overflow.\r
+ //\r
+ if ((UINT32) (~0) - Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress <\r
+ Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Read last byte of section header from file\r
+ //\r
+ Size = 1;\r
+ ReadSize = Size;\r
+ Status = ImageContext->ImageRead (\r
+ ImageContext->Handle,\r
+ Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress +\r
+ Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - 1,\r
+ &Size,\r
+ &BufferData\r
+ );\r
+ if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+ if (Size != ReadSize) {\r
+ Status = RETURN_UNSUPPORTED;\r
+ }\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r