13

It seems to me it's always going to be 4GB, because it uses the same size datatype (A DWORD)? Isn't a DWORD for the SizeOfImage always going to be 32-bits? Or am I mistaken about this limitation?

Answer

4GB does indeed to seem to be the hard limit of ALL Portable Executable's (32-bit and 64-bit PE+).

unixman83
  • 9,421
  • 10
  • 68
  • 102

3 Answers3

14

According to the spec it is 32-bit unsigned value for a PE32+ image just like a PE32 image.

However, in my testing with both 32-bit and 64-bit applications (PE32/PE32+ files) on Windows 7 SP1 Home Premium x64, the maximum file size for either is between 1.8-1.85GB.

I tested by creating a very basic C executable with Visual Studio (~8K for 32-bit and 9K for 64-bit) and the added an empty code section to the PE header until Windows would no longer load it, and then binary searched for the limit. Looking at the process with vmmap showed that almost all of the entire first 2GB of address space were the image (including any subsequently loaded DLLs such as kernel32.dll). The limit was the same for me with both 32 and 64-bit processes. The 64-bit process did have the flag set in it's NT Header's File Header's section stating that it could handle addresses >2GB. It also could allocate memory for non-image sections above the 2GB limit.

It seems like the image is required to fit in it's entirety in the lower 2GB of VA space for the process, which means the SizeOfImage is being treated a signed 32-bit integer by the loader effectively.

leezu
  • 512
  • 3
  • 17
Zach Burlingame
  • 13,476
  • 14
  • 56
  • 65
  • The pe spec in [COFF/PE spec][1] has a table in section 3.4.2 which has the SizeOfImage field's size mentioned as 4 bytes, this should mean that a PE file can theoretically be of size 2^32 bytes (4 GiB) at max. This conflicts with the 2GiB limit obtained by you. [1]:https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v83.docx – Sahil Singh Dec 12 '16 at 14:48
  • Can you also tell the name of the 64-bit flag you mention in your answer, which states that a file >2GiB can be handled? – Sahil Singh Dec 12 '16 at 14:49
  • 1
    Page 10 of the spec has the following line, "PE32+ images allow for a 64-bit address space while limiting the image size to 2 gigabytes". This explains you getting 2GiB as limit, however why is this a limit is not mentioned. – Sahil Singh Dec 12 '16 at 14:55
  • @SahilSingh that's not a conflict in the first place, the type of the field only allows you to specify those sizes, it says nothing about the OS' ability to actually load such an image – harold Dec 12 '16 at 16:39
  • @harold - then what is holding the OS back from being able to use PE files of 4 GiB? If it is not PE header, then what it is? – Sahil Singh Dec 13 '16 at 12:11
  • What was the error you have faced when you exceeded the limit? – Ayman Salah Jan 19 '20 at 20:28
8

According to the COFF/PE32 spec, the image size for a valid PE32+ (64 bit/(PE+) file is a 4 byte unsigned value.

Sahil Singh
  • 3,352
  • 39
  • 62
Bukes
  • 3,668
  • 1
  • 18
  • 20
  • Absolutely correct, and that means the limit is `2^(4*8)B - 1B = 4GiB - 1B`. I was able to verify it on Windows 10 64-bit by creating self-extracting archives with WinRAR in the form of .EXE-files. An executable with a size of `4GiB` won't launch, but `4GiB - 1B` works fine. – Robin Hartmann Oct 16 '19 at 22:38
1

The ImageSize field in the PE headers is largely unrelated to the file size on-disk of the PE file. ImageSize is the in-memory size of the loaded image i.e. the size of all sections (each rounded to the SectionAlignment boundary) + size of the PE headers (given in the next header field, SizeOfHeaders). This value cannot be > 2GB for either PE32 or PE32+ because a) the spec says so and b) there exist 31-bit RVAs in the spec, e.g. in the import lookup table. RVAs are memory references given as offsets from the in-memory base address.

That's in memory though. The file on disk can contain data that is not loaded into memory (e.g. debug data, cert data). File pointer fields in the PE spec are 32-bit unsigned values. So the theoretical maximum size of a PE file according to the spec is 4GB.

That's according to the spec. There may be file-system, loader, OS limits outside of the PE spec that reduce the maximum further.