Skip to content

Align final section to file alignment, not to virtual image size#124984

Open
jkoritzinsky wants to merge 1 commit intodotnet:mainfrom
jkoritzinsky:pe-file-size
Open

Align final section to file alignment, not to virtual image size#124984
jkoritzinsky wants to merge 1 commit intodotnet:mainfrom
jkoritzinsky:pe-file-size

Conversation

@jkoritzinsky
Copy link
Member

Fixes #124980

@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts how PEObjectWriter determines the final on-disk size of emitted PE files so the file is padded only to file alignment, rather than being extended to the PE’s virtual image size (SizeOfImage), addressing reported self-contained app size regressions.

Changes:

  • Stop padding the output stream length to sizeOfImage.
  • Pad the final file length to _peFileAlignment instead.

Debug.Assert(outputFileStream.Position <= sizeOfImage);
outputFileStream.SetLength(sizeOfImage);
// Ensure that the final file size is aligned to file alignment.
long paddedSize = AlignmentHelper.AlignUp((int)outputFileStream.Position, (int)_peFileAlignment);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outputFileStream.Position is a long, but it’s cast to int before calling AlignmentHelper.AlignUp. If the output ever exceeds 2GB, this unchecked cast can wrap negative and lead to an incorrect paddedSize (potential truncation or an exception from SetLength). Consider computing the alignment using 64-bit arithmetic (or at least using a checked cast and throwing a clear error when the file is too large).

Suggested change
long paddedSize = AlignmentHelper.AlignUp((int)outputFileStream.Position, (int)_peFileAlignment);
long position = outputFileStream.Position;
long fileAlignment = _peFileAlignment;
Debug.Assert(fileAlignment > 0);
long paddedSize = position;
if (fileAlignment > 0)
{
long remainder = position % fileAlignment;
if (remainder != 0)
{
paddedSize = position + (fileAlignment - remainder);
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +849 to +852
// Ensure that the final file size is aligned to file alignment.
long paddedSize = AlignmentHelper.AlignUp((int)outputFileStream.Position, (int)_peFileAlignment);

outputFileStream.SetLength(paddedSize);
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous Debug.Assert(outputFileStream.Position <= sizeOfImage) was a useful invariant check that the writer didn’t emit more raw bytes than the SizeOfImage value recorded in the PE optional header. Even though the file should no longer be padded to sizeOfImage, it would still be valuable to keep an assertion (or equivalent validation) here to catch layout/emit bugs that would otherwise produce an invalid PE.

Copilot uses AI. Check for mistakes.
Copy link
Member

@filipnavara filipnavara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me in principle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Filesize regressions in self-contained apps in .NET 11

3 participants