From 7d36386f53566513dc22195b5ad1487ea3a95cc7 Mon Sep 17 00:00:00 2001 From: Vitek Karas <10670590+vitek-karas@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:06:58 -0700 Subject: [PATCH] Fix corrupted debug header directory entry when writing multiple such entries. (#869) Basically the first two entries are written correctly, and any after that which has data will have the RVA correct, but the virtual address field will be wrong. Depending on the consumer this can work (if they use RVA) or fail (if they use virtual address) as they would read garbage data. Currently this mostly affects embedded protable PDBs since in that case we write 4 headers: CodeView, PdbChecksum, EmbeddedPdb and Deterministic (in this order), so the embedded PDB data is effectively wrong. Also adds a test which validates that both the RVA and virtual address point to the same thing. --- Mono.Cecil.PE/ImageWriter.cs | 2 +- Test/Mono.Cecil.Tests/PortablePdbTests.cs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Mono.Cecil.PE/ImageWriter.cs b/Mono.Cecil.PE/ImageWriter.cs index c2eb97a17..3d8d8898a 100644 --- a/Mono.Cecil.PE/ImageWriter.cs +++ b/Mono.Cecil.PE/ImageWriter.cs @@ -719,7 +719,7 @@ void BuildTextMap () entry.Directory = directory; data_len += entry.Data.Length; - data_address += data_len; + data_address += entry.Data.Length; } debug_dir_len = directories_len + data_len; diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs index bd524fd14..3aa0ffce8 100644 --- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs +++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -911,7 +911,7 @@ public void ReadEmbeddedPortablePdbChecksum () Assert.AreEqual ("SHA256", algorithmName); GetCodeViewPdbId (module, out byte [] pdbId); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); + GetEmbeddedPdb (module.Image, debugHeader, out byte [] embeddedPdb); CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out byte [] expectedPdbId); CollectionAssert.AreEqual (expectedChecksum, checksum); @@ -1005,7 +1005,7 @@ public void WriteEmbeddedPortablePdbChecksum () Assert.AreEqual ("SHA256", algorithmName); GetCodeViewPdbId (module, out byte [] pdbId); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); + GetEmbeddedPdb (module.Image, debugHeader, out byte [] embeddedPdb); CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out byte [] expectedPdbId); CollectionAssert.AreEqual (expectedChecksum, checksum); @@ -1026,7 +1026,7 @@ public void DoubleWriteEmbeddedPortablePdbChecksum () byte [] pdbIdOne; using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { var debugHeader = module.GetDebugHeader (); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); + GetEmbeddedPdb (module.Image, debugHeader, out byte [] embeddedPdb); CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out pdbIdOne); } @@ -1037,18 +1037,20 @@ public void DoubleWriteEmbeddedPortablePdbChecksum () byte [] pdbIdTwo; using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { var debugHeader = module.GetDebugHeader (); - GetEmbeddedPdb (debugHeader, out byte [] embeddedPdb); + GetEmbeddedPdb (module.Image, debugHeader, out byte [] embeddedPdb); CalculatePdbChecksumAndId (embeddedPdb, out byte [] expectedChecksum, out pdbIdTwo); } CollectionAssert.AreEqual (pdbIdOne, pdbIdTwo); } - private void GetEmbeddedPdb (ImageDebugHeader debugHeader, out byte [] embeddedPdb) + private void GetEmbeddedPdb (Image image, ImageDebugHeader debugHeader, out byte [] embeddedPdb) { var entry = Mixin.GetEmbeddedPortablePdbEntry (debugHeader); Assert.IsNotNull (entry); + Assert.AreEqual (entry.Directory.PointerToRawData, image.ResolveVirtualAddress ((uint)entry.Directory.AddressOfRawData)); + var compressed_stream = new MemoryStream (entry.Data); var reader = new BinaryStreamReader (compressed_stream); Assert.AreEqual (0x4244504D, reader.ReadInt32 ());