]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
Remove the ASSERT (FALSE) code, just return unsupported.
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index 69c649a32a1bc404f1d4a583d682985332a8b242..258455708ad11bce89558731b6f5101439811efc 100644 (file)
@@ -2,6 +2,19 @@
   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
+  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 - 2012, 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
@@ -48,7 +61,10 @@ PeCoffLoaderGetPeHeaderMagicValue (
 \r
 /**\r
   Retrieves the PE or TE Header from a PE/COFF or TE image. \r
-  Also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, \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
@@ -67,24 +83,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
@@ -104,14 +127,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
@@ -138,34 +165,58 @@ PeCoffLoaderGetPeHeader (
 \r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
-      // 1. Check FileHeader.SizeOfOptionalHeader filed.\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 OptionalHeader.SizeOfHeaders field.\r
-      // This field will be use like the following mode, so just compare the result.\r
-      // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.\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
-      if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1 < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {\r
-        if (Hdr.Pe32->OptionalHeader.SizeOfHeaders < (UINT32)((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) &Hdr)) {\r
-          return RETURN_UNSUPPORTED;\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) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32->FileHeader.NumberOfSections) {\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
       }\r
 \r
       //\r
-      // Read Hdr.Pe32.OptionalHeader.SizeOfHeaders data from file\r
+      // 4. Check the OptionalHeader.SizeOfHeaders field.\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)) {\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
@@ -181,13 +232,15 @@ PeCoffLoaderGetPeHeader (
           //\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
-            return RETURN_INVALID_PARAMETER;\r
+            ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+            return RETURN_UNSUPPORTED;\r
           }\r
 \r
           //\r
-          // Read section header from file\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
@@ -195,7 +248,11 @@ PeCoffLoaderGetPeHeader (
                                    &Size,\r
                                    &BufferData\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
@@ -211,34 +268,57 @@ PeCoffLoaderGetPeHeader (
 \r
     } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
       //\r
-      // 1. Check FileHeader.SizeOfOptionalHeader filed.\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
-      // 2. Check the OptionalHeader.SizeOfHeaders field.\r
-      // This field will be use like the following mode, so just compare the result.\r
-      // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.\r
+      // 3. Check the FileHeader.NumberOfSections field.\r
       //\r
-      if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1 < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {\r
-        if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders < (UINT32)((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) &Hdr)) {\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
-      // Read Hdr.Pe32.OptionalHeader.SizeOfHeaders data from file\r
+      // 4. Check the OptionalHeader.SizeOfHeaders field.\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)) {\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
@@ -254,13 +334,15 @@ PeCoffLoaderGetPeHeader (
           //\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
-            return RETURN_INVALID_PARAMETER;\r
+            ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+            return RETURN_UNSUPPORTED;\r
           }\r
 \r
           //\r
-          // Read section header from file\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
@@ -268,7 +350,11 @@ PeCoffLoaderGetPeHeader (
                                    &Size,\r
                                    &BufferData\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
@@ -303,28 +389,50 @@ PeCoffLoaderGetPeHeader (
   //\r
   // Check each section field.\r
   //\r
-  SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\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)) {\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
     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
-        return RETURN_INVALID_PARAMETER;\r
+        ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+        return RETURN_UNSUPPORTED;\r
       }\r
 \r
       //\r
@@ -332,13 +440,18 @@ PeCoffLoaderGetPeHeader (
       // 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)) {\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
@@ -368,7 +481,9 @@ PeCoffLoaderGetPeHeader (
   The ImageRead and Handle fields of ImageContext structure must be valid prior \r
   to invoking this service.\r
 \r
-  Also done many checks in PE image to make sure PE image DosHeader, PeOptionHeader, \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
@@ -390,6 +505,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
@@ -471,7 +587,8 @@ PeCoffLoaderGetImageInfo (
   // 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
+    ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+    return RETURN_UNSUPPORTED;\r
   }\r
 \r
   if (!(ImageContext->IsTeImage)) {\r
@@ -512,14 +629,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
@@ -539,16 +660,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 + 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
@@ -573,14 +704,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
@@ -626,14 +761,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 + 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
@@ -845,17 +984,16 @@ 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) || (RelocBase->SizeOfBlock > RelocDir->Size)) {\r
         ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
         return RETURN_LOAD_ERROR;\r
       }\r
 \r
+      RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
+\r
       if (!(ImageContext->IsTeImage)) {\r
         FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
         if (FixupBase == NULL) {\r
@@ -1004,7 +1142,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
@@ -1016,6 +1153,7 @@ PeCoffLoaderLoadImage (
   EFI_IMAGE_RESOURCE_DIRECTORY_STRING   *ResourceDirectoryString;\r
   EFI_IMAGE_RESOURCE_DATA_ENTRY         *ResourceDataEntry;\r
   CHAR16                                *String;\r
+  UINT32                                Offset;\r
 \r
 \r
   ASSERT (ImageContext != NULL);\r
@@ -1130,7 +1268,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
@@ -1161,10 +1299,6 @@ PeCoffLoaderLoadImage (
       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
@@ -1352,14 +1486,26 @@ PeCoffLoaderLoadImage (
 \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
         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
         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
@@ -1379,22 +1525,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
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && DirectoryEntry->Size != 0) {\r
       Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress);\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
@@ -1409,14 +1570,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
@@ -1425,6 +1606,10 @@ 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
                 break;\r
@@ -1570,6 +1755,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
@@ -1624,13 +1818,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
@@ -1663,6 +1850,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