-
Notifications
You must be signed in to change notification settings - Fork 586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check overlaps #536
Check overlaps #536
Conversation
6d2d621
to
3ec09b4
Compare
Hello, could you provide a way to reproduce this bug? |
If we have an issue with chunks that cannot be reused in |
Test.zip
Build it, and load in dnSpy: As we can see: |
Hello, I tried to reproduce this issue by running the following code: var mod = ModuleDefMD.Load("MetadataSizeChanged.exe");
var modOpts = new NativeModuleWriterOptions(mod, true);
mod.NativeWrite("final2.exe", modOpts); and also by opening |
My bad, I missed the part about the entry point name change! I'm now able to reproduce the issue and will look further into it! |
I came up with a much simpler solution for this issue of overlapping reused chunks (the check regarding overlapping could do some work). Add this code to var origEnd = origRva + origSize;
foreach (var reusedChunk in reusedChunks) {
var start = reusedChunk.RVA;
var end = start + reusedChunk.Chunk.GetVirtualSize();
if (start <= origRva && end > origRva)
return;
if (start <= origEnd && end > origEnd)
return;
if (origRva <= start && origEnd > start)
return;
if (origRva <= end && origEnd > end)
return;
} after if (origRva == 0 || origSize == 0)
return;
if (chunk is null)
return;
if (!chunk.CanReuse(origRva, origSize))
return;
if (((uint)origRva & (requiredAlignment - 1)) != 0)
return; |
Seems there're unnecessary so many checks: if (start <= origRva && end > origRva)
return;
if (start <= origEnd && end > origEnd)
return;
if (origRva <= start && origEnd > start)
return;
if (origRva <= end && origEnd > end)
return; => if (start < origEnd && end > origRva)
return; |
Yes, indeed. Here is the new void ReuseIfPossible(PESection section, IReuseChunk chunk, RVA origRva, uint origSize, uint requiredAlignment) {
if (origRva == 0 || origSize == 0)
return;
if (chunk is null)
return;
if (!chunk.CanReuse(origRva, origSize))
return;
if (((uint)origRva & (requiredAlignment - 1)) != 0)
return;
var origEnd = origRva + origSize;
foreach (var reusedChunk in reusedChunks) {
var start = reusedChunk.RVA;
var end = start + reusedChunk.Chunk.GetVirtualSize();
if (start < origEnd && end > origRva)
return;
}
if (section.Remove(chunk) is null)
throw new InvalidOperationException();
reusedChunks.Add(new ReusedChunkInfo(chunk, origRva));
} This fix is better than the one currently in the PR as it will only prevent the usage of overlapping chunks but will still reuse chunks that don't overlap. @wtfsck What do you think? |
Yes, the data in the region marked in red will be kept in the output file. This is by design for the native writer as the native writer reuses the original PE file and just adds/overwrites the old data with new data. If |
Is |
I used |
@ElektroKill Looks good assuming it fixed the repro above. @CreateAndInject Could you add that fix instead? |
3ec09b4
to
a45d40c
Compare
OK |
Thanks, it's been merged! |
When I saved a file, I got an invalid .NET file, since COR20 header signature is rewritten.