]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
Enhance the error code info.
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index 064917cd9ba76f78c3f3a08c08f09076704ce27d..60036e11be72091a7ac111384fe47fe03c92c818 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 - 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
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -47,7 +60,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 +83,30 @@ 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
+  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 +126,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
@@ -131,6 +163,83 @@ PeCoffLoaderGetPeHeader (
     Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
 \r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // 1. Check FileHeader.SizeOfOptionalHeader 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
+      //\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
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+      }\r
+\r
+      //\r
+      // 2.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 +249,83 @@ PeCoffLoaderGetPeHeader (
       ImageContext->SizeOfHeaders     = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
 \r
     } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+      //\r
+      // 1. Check FileHeader.SizeOfOptionalHeader 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
+      //\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
+      //\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
+          ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+          return RETURN_UNSUPPORTED;\r
+        }\r
+      }\r
+\r
+      //\r
+      // 2.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 +352,73 @@ 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
+    if (SectionHeader.SizeOfRawData > 0) {\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 +438,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 +462,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
@@ -285,7 +544,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
@@ -326,14 +586,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,14 +617,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
           if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
@@ -387,14 +655,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
@@ -440,14 +712,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
@@ -829,6 +1105,7 @@ PeCoffLoaderLoadImage (
   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY    *ResourceDirectoryEntry;\r
   EFI_IMAGE_RESOURCE_DIRECTORY_STRING   *ResourceDirectoryString;\r
   EFI_IMAGE_RESOURCE_DATA_ENTRY         *ResourceDataEntry;\r
+  CHAR16                                *String;\r
 \r
 \r
   ASSERT (ImageContext != NULL);\r
@@ -1208,12 +1485,19 @@ PeCoffLoaderLoadImage (
 \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
+              continue;\r
+            }\r
             ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset);\r
+            String = &ResourceDirectoryString->String[0];\r
 \r
             if (ResourceDirectoryString->Length == 3 &&\r
-                ResourceDirectoryString->String[0] == L'H' &&\r
-                ResourceDirectoryString->String[1] == L'I' &&\r
-                ResourceDirectoryString->String[2] == L'I') {\r
+                String[0] == L'H' &&\r
+                String[1] == L'I' &&\r
+                String[2] == L'I') {\r
               //\r
               // Resource Type "HII" found\r
               //\r
@@ -1382,6 +1666,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
@@ -1475,6 +1768,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