]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
MdePkg: Update Base.h to fix compilation issues with ICC.
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index 4bf5b7cbbc4d5ee4615ea5e6283975c373dabce6..33cad23a014e03998b9a0fcc53d7aca7560daf21 100644 (file)
@@ -2,7 +2,20 @@
   Base PE/COFF loader supports loading any PE32/PE32+ or TE image, but\r
   only supports relocating IA32, x64, IPF, and EBC images.\r
 \r
-  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Caution: This file requires additional review when modified.\r
+  This library will have external input - PE/COFF image.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  The basic guideline is that caller need provide ImageContext->ImageRead () with the\r
+  necessary data range check, to make sure when this library reads PE/COFF image, the\r
+  PE image buffer is always in valid range.\r
+  This library will also do some additional check for PE header fields.\r
+\r
+  PeCoffLoaderGetPeHeader() routine will do basic check for PE/COFF header.\r
+  PeCoffLoaderGetImageInfo() routine will do basic check for whole PE/COFF image.\r
+\r
+  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
 #include "BasePeCoffLibInternals.h"\r
 \r
+/**\r
+  Adjust some fields in section header for TE image.\r
+\r
+  @param  SectionHeader             Pointer to the section header.\r
+  @param  TeStrippedOffset          Size adjust for the TE image.\r
+\r
+**/\r
+VOID\r
+PeCoffLoaderAdjustOffsetForTeImage (\r
+  EFI_IMAGE_SECTION_HEADER              *SectionHeader,\r
+  UINT32                                TeStrippedOffset\r
+  )\r
+{\r
+  SectionHeader->VirtualAddress   -= TeStrippedOffset;\r
+  SectionHeader->PointerToRawData -= TeStrippedOffset;\r
+}\r
+\r
 /**\r
   Retrieves the magic value from the PE/COFF header.\r
 \r
@@ -47,7 +77,12 @@ PeCoffLoaderGetPeHeaderMagicValue (
 \r
 \r
 /**\r
-  Retrieves the PE or TE Header from a PE/COFF or TE image.\r
+  Retrieves the PE or TE Header from a PE/COFF or TE image. \r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this routine will \r
+  also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, \r
+  SizeOfHeader, Section Data Region and Security Data Region be in PE image range. \r
 \r
   @param  ImageContext    The context of the image being loaded.\r
   @param  Hdr             The buffer in which to return the PE32, PE32+, or TE header.\r
@@ -65,20 +100,31 @@ PeCoffLoaderGetPeHeader (
   RETURN_STATUS         Status;\r
   EFI_IMAGE_DOS_HEADER  DosHdr;\r
   UINTN                 Size;\r
+  UINTN                 ReadSize;\r
   UINT16                Magic;\r
+  UINT32                SectionHeaderOffset;\r
+  UINT32                Index;\r
+  UINT32                HeaderWithoutDataDir;\r
+  CHAR8                 BufferData;\r
+  UINTN                 NumberOfSections;\r
+  EFI_IMAGE_SECTION_HEADER  SectionHeader;\r
 \r
   //\r
   // Read the DOS image header to check for its existence\r
   //\r
   Size = sizeof (EFI_IMAGE_DOS_HEADER);\r
+  ReadSize = Size;\r
   Status = ImageContext->ImageRead (\r
                            ImageContext->Handle,\r
                            0,\r
                            &Size,\r
                            &DosHdr\r
                            );\r
-  if (RETURN_ERROR (Status)) {\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
@@ -98,14 +144,18 @@ PeCoffLoaderGetPeHeader (
   // location in both images.\r
   //\r
   Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+  ReadSize = Size;\r
   Status = ImageContext->ImageRead (\r
                            ImageContext->Handle,\r
                            ImageContext->PeCoffHeaderOffset,\r
                            &Size,\r
                            Hdr.Pe32\r
                            );\r
-  if (RETURN_ERROR (Status)) {\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
@@ -124,6 +174,50 @@ PeCoffLoaderGetPeHeader (
     ImageContext->SectionAlignment  = 0;\r
     ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;\r
 \r
+    //\r
+    // Check the StrippedSize.\r
+    //\r
+    if (sizeof (EFI_TE_IMAGE_HEADER) >= (UINT32)Hdr.Te->StrippedSize) {\r
+      ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Check the SizeOfHeaders field.\r
+    //\r
+    if (Hdr.Te->BaseOfCode <= Hdr.Te->StrippedSize) {\r
+      ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Read last byte of Hdr.Te->SizeOfHeaders from the file.\r
+    //\r
+    Size = 1;\r
+    ReadSize = Size;\r
+    Status = ImageContext->ImageRead (\r
+                             ImageContext->Handle,\r
+                             ImageContext->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
+    // TE Image Data Directory Entry size is non-zero, but the Data Directory Virtual Address is zero.\r
+    // This case is not a valid TE image. \r
+    //\r
+    if ((Hdr.Te->DataDirectory[0].Size != 0 && Hdr.Te->DataDirectory[0].VirtualAddress == 0) ||\r
+        (Hdr.Te->DataDirectory[1].Size != 0 && Hdr.Te->DataDirectory[1].VirtualAddress == 0)) {\r
+      ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
     ImageContext->IsTeImage = FALSE;\r
     ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;\r
@@ -131,6 +225,112 @@ PeCoffLoaderGetPeHeader (
     Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
 \r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // 1. Check OptionalHeader.NumberOfRvaAndSizes filed.\r
+      //\r
+      if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\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_HEADER32) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
+      if (((UINT32)Hdr.Pe32->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=\r
+          Hdr.Pe32->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.Pe32->FileHeader.SizeOfOptionalHeader;\r
+      //\r
+      // 3. Check the FileHeader.NumberOfSections field.\r
+      //\r
+      if (Hdr.Pe32->OptionalHeader.SizeOfImage <= SectionHeaderOffset) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+      if ((Hdr.Pe32->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32->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.Pe32->OptionalHeader.SizeOfHeaders <= SectionHeaderOffset) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+      if (Hdr.Pe32->OptionalHeader.SizeOfHeaders >= Hdr.Pe32->OptionalHeader.SizeOfImage) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+      if ((Hdr.Pe32->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32->FileHeader.NumberOfSections) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+\r
+      //\r
+      // 4.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file.\r
+      //\r
+      Size = 1;\r
+      ReadSize = Size;\r
+      Status = ImageContext->ImageRead (\r
+                               ImageContext->Handle,\r
+                               Hdr.Pe32->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.Pe32->OptionalHeader.NumberOfRvaAndSizes) {\r
+        if (Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size != 0) {\r
+          //\r
+          // Check the member data to avoid overflow.\r
+          //\r
+          if ((UINT32) (~0) - Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress <\r
+              Hdr.Pe32->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.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress +\r
+                                    Hdr.Pe32->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
       //\r
       // Use PE32 offset\r
       //\r
@@ -140,6 +340,111 @@ PeCoffLoaderGetPeHeader (
       ImageContext->SizeOfHeaders     = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
 \r
     } else if (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
       //\r
       // Use PE32+ offset\r
       //\r
@@ -166,6 +471,89 @@ PeCoffLoaderGetPeHeader (
     return RETURN_UNSUPPORTED;\r
   }\r
 \r
+  //\r
+  // Check each section field.\r
+  //\r
+  if (ImageContext->IsTeImage) {\r
+    SectionHeaderOffset = sizeof(EFI_TE_IMAGE_HEADER);\r
+    NumberOfSections    = (UINTN) (Hdr.Te->NumberOfSections);\r
+  } else {\r
+    SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
+    NumberOfSections    = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);\r
+  }\r
+\r
+  for (Index = 0; Index < NumberOfSections; Index++) {\r
+    //\r
+    // Read section header from file\r
+    //\r
+    Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+    ReadSize = Size;\r
+    Status = ImageContext->ImageRead (\r
+                             ImageContext->Handle,\r
+                             SectionHeaderOffset,\r
+                             &Size,\r
+                             &SectionHeader\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
+    // Adjust some field in Section Header for TE image.\r
+    //\r
+    if (ImageContext->IsTeImage) {\r
+      PeCoffLoaderAdjustOffsetForTeImage (&SectionHeader, (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+    }\r
+\r
+    if (SectionHeader.SizeOfRawData > 0) {\r
+      //\r
+      // Section data should bigger than the Pe header.\r
+      //\r
+      if (SectionHeader.VirtualAddress < ImageContext->SizeOfHeaders || \r
+          SectionHeader.PointerToRawData < ImageContext->SizeOfHeaders) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+\r
+      //\r
+      // Check the member data to avoid overflow.\r
+      //\r
+      if ((UINT32) (~0) - SectionHeader.PointerToRawData < SectionHeader.SizeOfRawData) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
+      }\r
+\r
+      //\r
+      // Base on the ImageRead function to check the section data field.\r
+      // Read the last byte to make sure the data is in the image region.\r
+      //\r
+      Size = 1;\r
+      ReadSize = Size;\r
+      Status = ImageContext->ImageRead (\r
+                               ImageContext->Handle,\r
+                               SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData - 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
+    // Check next section.\r
+    //\r
+    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+  }\r
+\r
   return RETURN_SUCCESS;\r
 }\r
 \r
@@ -185,6 +573,11 @@ PeCoffLoaderGetPeHeader (
   The ImageRead and Handle fields of ImageContext structure must be valid prior \r
   to invoking this service.\r
 \r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this routine will \r
+  also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, \r
+  SizeOfHeader, Section Data Region and Security Data Region be in PE image range. \r
+\r
   @param  ImageContext              The pointer to the image context structure that describes the PE/COFF\r
                                     image that needs to be examined by this function.\r
 \r
@@ -204,6 +597,7 @@ PeCoffLoaderGetImageInfo (
   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
   EFI_IMAGE_DATA_DIRECTORY              *DebugDirectoryEntry;\r
   UINTN                                 Size;\r
+  UINTN                                 ReadSize;\r
   UINTN                                 Index;\r
   UINTN                                 DebugDirectoryEntryRva;\r
   UINTN                                 DebugDirectoryEntryFileOffset;\r
@@ -212,6 +606,7 @@ PeCoffLoaderGetImageInfo (
   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       DebugEntry;\r
   UINT32                                NumberOfRvaAndSizes;\r
   UINT16                                Magic;\r
+  UINT32                                TeStrippedOffset;\r
 \r
   if (ImageContext == NULL) {\r
     return RETURN_INVALID_PARAMETER;\r
@@ -233,6 +628,7 @@ PeCoffLoaderGetImageInfo (
   // Retrieve the base address of the image\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
+    TeStrippedOffset = 0;\r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
@@ -245,7 +641,8 @@ PeCoffLoaderGetImageInfo (
       ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;\r
     }\r
   } else {\r
-    ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+    TeStrippedOffset = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
+    ImageContext->ImageAddress = (PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + TeStrippedOffset);\r
   }\r
 \r
   //\r
@@ -279,14 +676,6 @@ PeCoffLoaderGetImageInfo (
   } else {\r
     ImageContext->RelocationsStripped = FALSE;\r
   }\r
-  \r
-  //\r
-  // TE Image Relocation Data Directory Entry size is non-zero, but the Relocation Data Directory Virtual Address is zero.\r
-  // This case is not a valid TE image. \r
-  //\r
-  if ((ImageContext->IsTeImage) && (Hdr.Te->DataDirectory[0].Size != 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {\r
-    return RETURN_INVALID_PARAMETER;\r
-  }\r
 \r
   if (!(ImageContext->IsTeImage)) {\r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
@@ -326,14 +715,18 @@ PeCoffLoaderGetImageInfo (
         // Read section header from file\r
         //\r
         Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+        ReadSize = Size;\r
         Status = ImageContext->ImageRead (\r
                                  ImageContext->Handle,\r
                                  SectionHeaderOffset,\r
                                  &Size,\r
                                  &SectionHeader\r
                                  );\r
-        if (RETURN_ERROR (Status)) {\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
@@ -353,16 +746,26 @@ PeCoffLoaderGetImageInfo (
           // Read next debug directory entry\r
           //\r
           Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
+          ReadSize = Size;\r
           Status = ImageContext->ImageRead (\r
                                    ImageContext->Handle,\r
-                                   DebugDirectoryEntryFileOffset,\r
+                                   DebugDirectoryEntryFileOffset + Index,\r
                                    &Size,\r
                                    &DebugEntry\r
                                    );\r
-          if (RETURN_ERROR (Status)) {\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
+          // From PeCoff spec, when DebugEntry.RVA == 0 means this debug info will not load into memory.\r
+          // Here we will always load EFI_IMAGE_DEBUG_TYPE_CODEVIEW type debug info. so need adjust the\r
+          // ImageContext->ImageSize when DebugEntry.RVA == 0.\r
+          //\r
           if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
             ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);\r
             if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {\r
@@ -387,14 +790,18 @@ PeCoffLoaderGetImageInfo (
       // Read section header from file\r
       //\r
       Size   = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+      ReadSize = Size;\r
       Status = ImageContext->ImageRead (\r
                                ImageContext->Handle,\r
                                SectionHeaderOffset,\r
                                &Size,\r
                                &SectionHeader\r
                                );\r
-      if (RETURN_ERROR (Status)) {\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
@@ -402,9 +809,8 @@ PeCoffLoaderGetImageInfo (
           DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
         DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -\r
                                         SectionHeader.VirtualAddress +\r
-                                        SectionHeader.PointerToRawData +\r
-                                        sizeof (EFI_TE_IMAGE_HEADER) -\r
-                                        Hdr.Te->StrippedSize;\r
+                                        SectionHeader.PointerToRawData -\r
+                                        TeStrippedOffset;\r
 \r
         //\r
         // File offset of the debug directory was found, if this is not the last\r
@@ -428,7 +834,7 @@ PeCoffLoaderGetImageInfo (
       // Section Table.  \r
       //\r
       if ((++Index) == (UINTN)Hdr.Te->NumberOfSections) {\r
-        ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize);\r
+        ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) - TeStrippedOffset;\r
       }\r
 \r
       SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
@@ -440,14 +846,18 @@ PeCoffLoaderGetImageInfo (
         // Read next debug directory entry\r
         //\r
         Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
+        ReadSize = Size;\r
         Status = ImageContext->ImageRead (\r
                                  ImageContext->Handle,\r
-                                 DebugDirectoryEntryFileOffset,\r
+                                 DebugDirectoryEntryFileOffset + Index,\r
                                  &Size,\r
                                  &DebugEntry\r
                                  );\r
-        if (RETURN_ERROR (Status)) {\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
@@ -466,8 +876,9 @@ PeCoffLoaderGetImageInfo (
 /**\r
   Converts an image address to the loaded address.\r
 \r
-  @param  ImageContext  The context of the image being loaded.\r
-  @param  Address       The relative virtual address to be converted to the loaded address.\r
+  @param  ImageContext      The context of the image being loaded.\r
+  @param  Address           The address to be converted to the loaded address.\r
+  @param  TeStrippedOffset  Stripped offset for TE image.\r
 \r
   @return The converted address or NULL if the address can not be converted.\r
 \r
@@ -475,18 +886,19 @@ PeCoffLoaderGetImageInfo (
 VOID *\r
 PeCoffLoaderImageAddress (\r
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,\r
-  IN     UINTN                                 Address\r
+  IN     UINTN                                 Address, \r
+  IN     UINTN                                 TeStrippedOffset\r
   )\r
 {\r
   //\r
   // Make sure that Address and ImageSize is correct for the loaded image.\r
   //\r
-  if (Address >= ImageContext->ImageSize) {\r
+  if (Address >= ImageContext->ImageSize + TeStrippedOffset) {\r
     ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
     return NULL;\r
   }\r
 \r
-  return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address);\r
+  return (CHAR8 *)((UINTN) ImageContext->ImageAddress + Address - TeStrippedOffset);\r
 }\r
 \r
 /**\r
@@ -529,6 +941,7 @@ PeCoffLoaderRelocateImage (
   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
   EFI_IMAGE_DATA_DIRECTORY              *RelocDir;\r
   UINT64                                Adjust;\r
+  EFI_IMAGE_BASE_RELOCATION             *RelocBaseOrg;\r
   EFI_IMAGE_BASE_RELOCATION             *RelocBase;\r
   EFI_IMAGE_BASE_RELOCATION             *RelocBaseEnd;\r
   UINT16                                *Reloc;\r
@@ -542,6 +955,7 @@ PeCoffLoaderRelocateImage (
   PHYSICAL_ADDRESS                      BaseAddress;\r
   UINT32                                NumberOfRvaAndSizes;\r
   UINT16                                Magic;\r
+  UINT32                                TeStrippedOffset;\r
 \r
   ASSERT (ImageContext != NULL);\r
 \r
@@ -572,7 +986,7 @@ PeCoffLoaderRelocateImage (
 \r
   if (!(ImageContext->IsTeImage)) {\r
     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
-\r
+    TeStrippedOffset = 0;\r
     Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
 \r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
@@ -605,48 +1019,40 @@ PeCoffLoaderRelocateImage (
     // is present in the image. You have to check the NumberOfRvaAndSizes in\r
     // the optional header to verify a desired directory entry is there.\r
     //\r
-\r
-    if ((NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && (RelocDir->Size > 0)) {\r
-      RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
-      RelocBaseEnd = PeCoffLoaderImageAddress (\r
-                      ImageContext,\r
-                      RelocDir->VirtualAddress + RelocDir->Size - 1\r
-                      );\r
-      if (RelocBase == NULL || RelocBaseEnd == NULL) {\r
-        return RETURN_LOAD_ERROR;\r
-      }\r
-    } else {\r
-      //\r
-      // Set base and end to bypass processing below.\r
-      //\r
-      RelocBase = RelocBaseEnd = NULL;\r
+    if ((NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC)) {\r
+      RelocDir = NULL;\r
     }\r
   } else {\r
     Hdr.Te             = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);\r
-    Adjust             = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->ImageBase);\r
+    TeStrippedOffset   = (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
+    Adjust             = (UINT64) (BaseAddress - (Hdr.Te->ImageBase + TeStrippedOffset));\r
     if (Adjust != 0) {\r
-      Hdr.Te->ImageBase  = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
+      Hdr.Te->ImageBase  = (UINT64) (BaseAddress - TeStrippedOffset);\r
     }\r
 \r
     //\r
     // Find the relocation block\r
     //\r
     RelocDir = &Hdr.Te->DataDirectory[0];\r
-    if (RelocDir->Size > 0) {\r
-      RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
-                                      ImageContext->ImageAddress +\r
-                                      RelocDir->VirtualAddress +\r
-                                      sizeof(EFI_TE_IMAGE_HEADER) -\r
-                                      Hdr.Te->StrippedSize\r
-                                      );\r
-      RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
-    } else {\r
-      //\r
-      // Set base and end to bypass processing below.\r
-      //\r
-      RelocBase = RelocBaseEnd = NULL;    \r
+  }\r
+\r
+  if ((RelocDir != NULL) && (RelocDir->Size > 0)) {\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);\r
+    RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (ImageContext,\r
+                                                                            RelocDir->VirtualAddress + RelocDir->Size - 1,\r
+                                                                            TeStrippedOffset\r
+                                                                            );\r
+    if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {\r
+      ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+      return RETURN_LOAD_ERROR;\r
     }\r
+  } else {\r
+    //\r
+    // Set base and end to bypass processing below.\r
+    //\r
+    RelocBase = RelocBaseEnd = NULL;    \r
   }\r
+  RelocBaseOrg = RelocBase;\r
 \r
   //\r
   // If Adjust is not zero, then apply fix ups to the image\r
@@ -659,36 +1065,38 @@ PeCoffLoaderRelocateImage (
     while (RelocBase < RelocBaseEnd) {\r
 \r
       Reloc     = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
-      RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
-      \r
       //\r
-      // Make sure RelocEnd is in the Image range.\r
+      // Add check for RelocBase->SizeOfBlock field.\r
       //\r
-      if ((CHAR8 *) RelocEnd < (CHAR8 *)((UINTN) ImageContext->ImageAddress) ||\r
-          (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + (UINTN)ImageContext->ImageSize)) {\r
+      if (RelocBase->SizeOfBlock == 0) {\r
+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+        return RETURN_LOAD_ERROR;\r
+      }\r
+      if ((UINTN)RelocBase > MAX_ADDRESS - RelocBase->SizeOfBlock) {\r
         ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
         return RETURN_LOAD_ERROR;\r
       }\r
 \r
-      if (!(ImageContext->IsTeImage)) {\r
-        FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
-        if (FixupBase == NULL) {\r
-          return RETURN_LOAD_ERROR;\r
-        }\r
-      } else {\r
-        FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
-                      RelocBase->VirtualAddress +\r
-                      sizeof(EFI_TE_IMAGE_HEADER) -\r
-                      Hdr.Te->StrippedSize\r
-                      );\r
-      }    \r
+      RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
+      if ((UINTN)RelocEnd > (UINTN)RelocBaseOrg + RelocDir->Size) {\r
+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+        return RETURN_LOAD_ERROR;\r
+      }\r
+      FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress, TeStrippedOffset);\r
+      if (FixupBase == NULL) {\r
+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+        return RETURN_LOAD_ERROR;\r
+      }  \r
 \r
       //\r
       // Run this relocation record\r
       //\r
       while (Reloc < RelocEnd) {\r
-\r
-        Fixup = FixupBase + (*Reloc & 0xFFF);\r
+        Fixup = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), TeStrippedOffset);\r
+        if (Fixup == NULL) {\r
+          ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+          return RETURN_LOAD_ERROR;\r
+        }\r
         switch ((*Reloc) >> 12) {\r
         case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
           break;\r
@@ -755,6 +1163,7 @@ PeCoffLoaderRelocateImage (
       //\r
       RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
     }\r
+    ASSERT ((UINTN)FixupData <= (UINTN)ImageContext->FixupData + ImageContext->FixupDataSize);\r
 \r
     //\r
     // Adjust the EntryPoint to match the linked-to address\r
@@ -818,7 +1227,6 @@ PeCoffLoaderLoadImage (
   UINTN                                 Index;\r
   CHAR8                                 *Base;\r
   CHAR8                                 *End;\r
-  CHAR8                                 *MaxEnd;\r
   EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;\r
   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;\r
   UINTN                                 Size;\r
@@ -830,7 +1238,8 @@ PeCoffLoaderLoadImage (
   EFI_IMAGE_RESOURCE_DIRECTORY_STRING   *ResourceDirectoryString;\r
   EFI_IMAGE_RESOURCE_DATA_ENTRY         *ResourceDataEntry;\r
   CHAR16                                *String;\r
-\r
+  UINT32                                Offset;\r
+  UINT32                                TeStrippedOffset;\r
 \r
   ASSERT (ImageContext != NULL);\r
 \r
@@ -917,6 +1326,7 @@ PeCoffLoaderLoadImage (
                       Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
       );\r
     NumberOfSections = (UINTN) (Hdr.Pe32->FileHeader.NumberOfSections);\r
+    TeStrippedOffset = 0;\r
   } else {\r
     Status = ImageContext->ImageRead (\r
                             ImageContext->Handle,\r
@@ -926,13 +1336,12 @@ PeCoffLoaderLoadImage (
                             );\r
 \r
     Hdr.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);\r
-\r
     FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
                       (UINTN)ImageContext->ImageAddress +\r
                       sizeof(EFI_TE_IMAGE_HEADER)\r
                       );\r
     NumberOfSections  = (UINTN) (Hdr.Te->NumberOfSections);\r
-\r
+    TeStrippedOffset  = (UINT32) Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
   }\r
 \r
   if (RETURN_ERROR (Status)) {\r
@@ -944,7 +1353,7 @@ PeCoffLoaderLoadImage (
   // Load each section of the image\r
   //\r
   Section = FirstSection;\r
-  for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {\r
+  for (Index = 0; Index < NumberOfSections; Index++) {\r
     //\r
     // Read the section\r
     //\r
@@ -956,11 +1365,8 @@ PeCoffLoaderLoadImage (
     //\r
     // Compute sections address\r
     //\r
-    Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);\r
-    End = PeCoffLoaderImageAddress (\r
-            ImageContext,\r
-            Section->VirtualAddress + Section->Misc.VirtualSize - 1\r
-            );\r
+    Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress, TeStrippedOffset);\r
+    End  = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress + Section->Misc.VirtualSize - 1, TeStrippedOffset);\r
 \r
     //\r
     // If the size of the section is non-zero and the base address or end address resolved to 0, then fail.\r
@@ -970,32 +1376,13 @@ PeCoffLoaderLoadImage (
       return RETURN_LOAD_ERROR;\r
     }\r
 \r
-    if (ImageContext->IsTeImage) {\r
-      Base = (CHAR8 *)((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);\r
-      End  = (CHAR8 *)((UINTN) End +  sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize);\r
-    }\r
-\r
-    if (End > MaxEnd) {\r
-      MaxEnd = End;\r
-    }\r
-\r
     if (Section->SizeOfRawData > 0) {\r
-      if (!(ImageContext->IsTeImage)) {\r
-        Status = ImageContext->ImageRead (\r
-                                ImageContext->Handle,\r
-                                Section->PointerToRawData,\r
-                                &Size,\r
-                                Base\r
-                                );\r
-      } else {\r
-        Status = ImageContext->ImageRead (\r
-                                ImageContext->Handle,\r
-                                Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN)Hdr.Te->StrippedSize,\r
-                                &Size,\r
-                                Base\r
-                                );\r
-      }\r
-\r
+      Status = ImageContext->ImageRead (\r
+                              ImageContext->Handle,\r
+                              Section->PointerToRawData - TeStrippedOffset,\r
+                              &Size,\r
+                              Base\r
+                              );\r
       if (RETURN_ERROR (Status)) {\r
         ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
         return Status;\r
@@ -1030,7 +1417,8 @@ PeCoffLoaderLoadImage (
       //\r
       ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (\r
                                                             ImageContext,\r
-                                                            (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint\r
+                                                            (UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint,\r
+                                                            0\r
                                                             );\r
     } else {\r
       //\r
@@ -1038,16 +1426,16 @@ PeCoffLoaderLoadImage (
       //\r
       ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (\r
                                                             ImageContext,\r
-                                                            (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint\r
+                                                            (UINTN)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint,\r
+                                                            0\r
                                                             );\r
     }\r
   } else {\r
-    ImageContext->EntryPoint =  (PHYSICAL_ADDRESS) (\r
-                                (UINTN)ImageContext->ImageAddress  +\r
-                                (UINTN)Hdr.Te->AddressOfEntryPoint +\r
-                                (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
-                                (UINTN)Hdr.Te->StrippedSize\r
-                                );\r
+    ImageContext->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)PeCoffLoaderImageAddress (\r
+                                                          ImageContext,\r
+                                                          (UINTN)Hdr.Te->AddressOfEntryPoint,\r
+                                                          TeStrippedOffset\r
+                                                          );\r
   }\r
 \r
   //\r
@@ -1072,14 +1460,17 @@ PeCoffLoaderLoadImage (
       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
     }\r
 \r
+    //\r
+    // Must use UINT64 here, because there might a case that 32bit loader to load 64bit image.\r
+    //\r
     if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
-      ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
+      ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64);\r
     } else {\r
       ImageContext->FixupDataSize = 0;\r
     }\r
   } else {\r
     DirectoryEntry              = &Hdr.Te->DataDirectory[0];\r
-    ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
+    ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINT64);\r
   }\r
   //\r
   // Consumer must allocate a buffer for the relocation fixup log.\r
@@ -1091,95 +1482,82 @@ PeCoffLoaderLoadImage (
   // Load the Codeview information if present\r
   //\r
   if (ImageContext->DebugDirectoryEntryRva != 0) {\r
-    if (!(ImageContext->IsTeImage)) {\r
-      DebugEntry = PeCoffLoaderImageAddress (\r
-                    ImageContext,\r
-                    ImageContext->DebugDirectoryEntryRva\r
-                    );\r
-    } else {\r
-      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(\r
-                      ImageContext->ImageAddress +\r
-                      ImageContext->DebugDirectoryEntryRva +\r
-                      sizeof(EFI_TE_IMAGE_HEADER) -\r
-                      Hdr.Te->StrippedSize\r
-                      );\r
+    DebugEntry = PeCoffLoaderImageAddress (\r
+                ImageContext,\r
+                ImageContext->DebugDirectoryEntryRva,\r
+                TeStrippedOffset\r
+                );\r
+    if (DebugEntry == NULL) {\r
+      ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+      return RETURN_LOAD_ERROR;\r
     }\r
 \r
-    if (DebugEntry != NULL) {\r
-      TempDebugEntryRva = DebugEntry->RVA;\r
-      if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {\r
-        Section--;\r
-        if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
-          TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;\r
-        } else {\r
-          TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;\r
-        }\r
+    TempDebugEntryRva = DebugEntry->RVA;\r
+    if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {\r
+      Section--;\r
+      if ((UINTN)Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
+        TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;\r
+      } else {\r
+        TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;\r
       }\r
+    }\r
 \r
-      if (TempDebugEntryRva != 0) {\r
-        if (!(ImageContext->IsTeImage)) {\r
-          ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);\r
-        } else {\r
-          ImageContext->CodeView = (VOID *)(\r
-                                    (UINTN)ImageContext->ImageAddress +\r
-                                    (UINTN)TempDebugEntryRva +\r
-                                    (UINTN)sizeof (EFI_TE_IMAGE_HEADER) -\r
-                                    (UINTN) Hdr.Te->StrippedSize\r
-                                    );\r
-        }\r
+    if (TempDebugEntryRva != 0) {\r
+      ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva, TeStrippedOffset); \r
+      if (ImageContext->CodeView == NULL) {\r
+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+        return RETURN_LOAD_ERROR;\r
+      }\r
 \r
-        if (ImageContext->CodeView == NULL) {\r
+      if (DebugEntry->RVA == 0) {\r
+        Size = DebugEntry->SizeOfData;\r
+        Status = ImageContext->ImageRead (\r
+                                ImageContext->Handle,\r
+                                DebugEntry->FileOffset - TeStrippedOffset,\r
+                                &Size,\r
+                                ImageContext->CodeView\r
+                                );\r
+        //\r
+        // Should we apply fix up to this field according to the size difference between PE and TE?\r
+        // Because now we maintain TE header fields unfixed, this field will also remain as they are\r
+        // in original PE image.\r
+        //\r
+\r
+        if (RETURN_ERROR (Status)) {\r
           ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
           return RETURN_LOAD_ERROR;\r
         }\r
 \r
-        if (DebugEntry->RVA == 0) {\r
-          Size = DebugEntry->SizeOfData;\r
-          if (!(ImageContext->IsTeImage)) {\r
-            Status = ImageContext->ImageRead (\r
-                                    ImageContext->Handle,\r
-                                    DebugEntry->FileOffset,\r
-                                    &Size,\r
-                                    ImageContext->CodeView\r
-                                    );\r
-          } else {\r
-            Status = ImageContext->ImageRead (\r
-                                    ImageContext->Handle,\r
-                                    DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize,\r
-                                    &Size,\r
-                                    ImageContext->CodeView\r
-                                    );\r
-            //\r
-            // Should we apply fix up to this field according to the size difference between PE and TE?\r
-            // Because now we maintain TE header fields unfixed, this field will also remain as they are\r
-            // in original PE image.\r
-            //\r
-          }\r
-\r
-          if (RETURN_ERROR (Status)) {\r
-            ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
-            return RETURN_LOAD_ERROR;\r
-          }\r
+        DebugEntry->RVA = TempDebugEntryRva;\r
+      }\r
 \r
-          DebugEntry->RVA = TempDebugEntryRva;\r
+      switch (*(UINT32 *) ImageContext->CodeView) {\r
+      case CODEVIEW_SIGNATURE_NB10:\r
+        if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
         }\r
+        ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
+        break;\r
 \r
-        switch (*(UINT32 *) ImageContext->CodeView) {\r
-        case CODEVIEW_SIGNATURE_NB10:\r
-          ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
-          break;\r
-\r
-        case CODEVIEW_SIGNATURE_RSDS:\r
-          ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
-          break;\r
-\r
-        case CODEVIEW_SIGNATURE_MTOC:\r
-          ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);\r
-          break;\r
+      case CODEVIEW_SIGNATURE_RSDS:\r
+        if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+        ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
+        break;\r
 \r
-        default:\r
-          break;\r
+      case CODEVIEW_SIGNATURE_MTOC:\r
+        if (DebugEntry->SizeOfData < sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
         }\r
+        ImageContext->PdbPointer = (CHAR8 *)ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);\r
+        break;\r
+\r
+      default:\r
+        break;\r
       }\r
     }\r
   }\r
@@ -1193,22 +1571,37 @@ PeCoffLoaderLoadImage (
       //\r
       // Use PE32 offset\r
       //\r
+      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];\r
     } else {\r
       //\r
       // Use PE32+ offset\r
       //\r
+      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];\r
     }\r
 \r
-    if (DirectoryEntry->Size != 0) {\r
-      Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress);\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && DirectoryEntry->Size != 0) {\r
+      Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress, 0);\r
       if (Base != NULL) {\r
         ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base;\r
+        Offset = sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * \r
+               (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);\r
+        if (Offset > DirectoryEntry->Size) {\r
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
         ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
 \r
         for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) {\r
           if (ResourceDirectoryEntry->u1.s.NameIsString) {\r
+            //\r
+            // Check the ResourceDirectoryEntry->u1.s.NameOffset before use it.\r
+            //\r
+            if (ResourceDirectoryEntry->u1.s.NameOffset >= DirectoryEntry->Size) {\r
+              ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+              return RETURN_UNSUPPORTED;\r
+            }\r
             ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset);\r
             String = &ResourceDirectoryString->String[0];\r
 \r
@@ -1223,14 +1616,34 @@ PeCoffLoaderLoadImage (
                 //\r
                 // Move to next level - resource Name\r
                 //\r
+                if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) {\r
+                  ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+                  return RETURN_UNSUPPORTED;\r
+                }\r
                 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+                Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + \r
+                         sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);\r
+                if (Offset > DirectoryEntry->Size) {\r
+                  ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+                  return RETURN_UNSUPPORTED;\r
+                }\r
                 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
 \r
                 if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
                   //\r
                   // Move to next level - resource Language\r
                   //\r
+                  if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >= DirectoryEntry->Size) {\r
+                    ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+                    return RETURN_UNSUPPORTED;\r
+                  }\r
                   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+                  Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + \r
+                           sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) * (ResourceDirectory->NumberOfNamedEntries + ResourceDirectory->NumberOfIdEntries);\r
+                  if (Offset > DirectoryEntry->Size) {\r
+                    ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+                    return RETURN_UNSUPPORTED;\r
+                  }\r
                   ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
                 }\r
               }\r
@@ -1239,8 +1652,12 @@ PeCoffLoaderLoadImage (
               // Now it ought to be resource Data\r
               //\r
               if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+                if (ResourceDirectoryEntry->u2.OffsetToData >= DirectoryEntry->Size) {\r
+                  ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+                  return RETURN_UNSUPPORTED;\r
+                }\r
                 ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (Base + ResourceDirectoryEntry->u2.OffsetToData);\r
-                ImageContext->HiiResourceData = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData);\r
+                ImageContext->HiiResourceData = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData, 0);\r
                 break;\r
               }\r
             }\r
@@ -1384,6 +1801,15 @@ PeCoffLoaderRelocateImageForRuntime (
   //\r
   FixupData = RelocationData;\r
   while (RelocBase < RelocBaseEnd) {\r
+    //\r
+    // Add check for RelocBase->SizeOfBlock field.\r
+    //\r
+    if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) {\r
+      //\r
+      // Data invalid, cannot continue to relocate the image, just return.\r
+      //\r
+      return;\r
+    }\r
 \r
     Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
     RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
@@ -1438,13 +1864,6 @@ PeCoffLoaderRelocateImageForRuntime (
         FixupData = FixupData + sizeof (UINT64);\r
         break;\r
 \r
-      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
-        //\r
-        // Not valid Relocation type for UEFI image, ASSERT\r
-        //\r
-        ASSERT (FALSE);\r
-        break;\r
-\r
       default:\r
         //\r
         // Only Itanium requires ConvertPeImage_Ex\r
@@ -1477,6 +1896,8 @@ PeCoffLoaderRelocateImageForRuntime (
   PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer.  \r
   The size of the buffer actually read is returned in ReadSize.\r
   \r
+  The caller must make sure the FileOffset and ReadSize within the file scope.\r
+\r
   If FileHandle is NULL, then ASSERT().\r
   If ReadSize is NULL, then ASSERT().\r
   If Buffer is NULL, then ASSERT().\r