Skip to content

Commit

Permalink
Fix corrupted debug header directory entry when writing multiple such…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
vitek-karas committed Sep 29, 2022
1 parent 6f94613 commit 7d36386
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Mono.Cecil.PE/ImageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 7 additions & 5 deletions Test/Mono.Cecil.Tests/PortablePdbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

Expand All @@ -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 ());
Expand Down

0 comments on commit 7d36386

Please sign in to comment.