diff --git a/src/AsmResolver.PE.File/Headers/SectionHeader.cs b/src/AsmResolver.PE.File/Headers/SectionHeader.cs index f2a72e7d0..a5de4f389 100644 --- a/src/AsmResolver.PE.File/Headers/SectionHeader.cs +++ b/src/AsmResolver.PE.File/Headers/SectionHeader.cs @@ -19,35 +19,6 @@ public class SectionHeader : SegmentBase, IOffsetConverter private string _name; - /// - /// Reads a single section header at the current position of the provided input stream. - /// - /// The input stream to read from. - /// The section header that was read. - public static SectionHeader FromReader(ref BinaryStreamReader reader) - { - ulong offset = reader.Offset; - uint rva = reader.Rva; - - var nameBytes = new byte[8]; - reader.ReadBytes(nameBytes, 0, nameBytes.Length); - - return new SectionHeader(Encoding.UTF8.GetString(nameBytes).Replace("\0", ""), 0) - { - Offset = offset, - Rva = rva, - VirtualSize = reader.ReadUInt32(), - VirtualAddress = reader.ReadUInt32(), - SizeOfRawData = reader.ReadUInt32(), - PointerToRawData = reader.ReadUInt32(), - PointerToRelocations = reader.ReadUInt32(), - PointerToLineNumbers = reader.ReadUInt32(), - NumberOfRelocations = reader.ReadUInt16(), - NumberOfLineNumbers = reader.ReadUInt16(), - Characteristics = (SectionFlags) reader.ReadUInt32() - }; - } - /// /// Creates a new section header with the provided name. /// @@ -194,6 +165,46 @@ public SectionFlags Characteristics set; } + /// + /// Reads a single section header at the current position of the provided input stream. + /// + /// The input stream to read from. + /// The section header that was read. + public static SectionHeader FromReader(ref BinaryStreamReader reader) + { + ulong offset = reader.Offset; + uint rva = reader.Rva; + + // Read name field. + byte[] nameBytes = new byte[8]; + reader.ReadBytes(nameBytes, 0, nameBytes.Length); + + // Interpret as UTF-8, discarding all invalid UTF-8 characters. + string name = Encoding.UTF8.GetString(nameBytes).Replace("\xfffd", ""); + + // Trim to last null-byte if it exists. + int index = name.IndexOf('\0'); + if (index >= 0) + name = name.Remove(index); + + return new SectionHeader(name, 0) + { + Offset = offset, + Rva = rva, + + // Read remainder of section header. + VirtualSize = reader.ReadUInt32(), + VirtualAddress = reader.ReadUInt32(), + SizeOfRawData = reader.ReadUInt32(), + PointerToRawData = reader.ReadUInt32(), + PointerToRelocations = reader.ReadUInt32(), + PointerToLineNumbers = reader.ReadUInt32(), + NumberOfRelocations = reader.ReadUInt16(), + NumberOfLineNumbers = reader.ReadUInt16(), + Characteristics = (SectionFlags) reader.ReadUInt32() + }; + } + /// public override uint GetPhysicalSize() => SectionHeaderSize; diff --git a/test/AsmResolver.PE.File.Tests/PEFileTest.cs b/test/AsmResolver.PE.File.Tests/PEFileTest.cs index 7a1c47463..5ce0a2b96 100644 --- a/test/AsmResolver.PE.File.Tests/PEFileTest.cs +++ b/test/AsmResolver.PE.File.Tests/PEFileTest.cs @@ -240,5 +240,19 @@ public void RemoveExistingEofData() var newFile = PEFile.FromBytes(newFileBytes); Assert.Null(newFile.EofData); } + + [Fact] + public void ReadSections() + { + var file = PEFile.FromBytes(Properties.Resources.HelloWorld); + Assert.Equal(new[] {".text", ".rsrc", ".reloc"}, file.Sections.Select(x => x.Name)); + } + + [Fact] + public void ReadInvalidSectionName() + { + var file = PEFile.FromBytes(Properties.Resources.HelloWorld_InvalidSectionName); + Assert.Equal(new[] {".text", ".rsrc", ".reloc"}, file.Sections.Select(x => x.Name)); + } } } diff --git a/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs b/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs index f2f817fd5..57a37ab19 100644 --- a/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs +++ b/test/AsmResolver.PE.File.Tests/Properties/Resources.Designer.cs @@ -90,6 +90,16 @@ public static byte[] HelloWorld_EOF { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + public static byte[] HelloWorld_InvalidSectionName { + get { + object obj = ResourceManager.GetObject("HelloWorld_InvalidSectionName", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/test/AsmResolver.PE.File.Tests/Properties/Resources.resx b/test/AsmResolver.PE.File.Tests/Properties/Resources.resx index c33ee0174..b075ab67e 100644 --- a/test/AsmResolver.PE.File.Tests/Properties/Resources.resx +++ b/test/AsmResolver.PE.File.Tests/Properties/Resources.resx @@ -127,7 +127,10 @@ ..\Resources\HelloWorld.EOF.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\NativeMemoryDemos.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + ..\Resources\HelloWorld.InvalidSectionName.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\NativeMemoryDemos.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + diff --git a/test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe b/test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe new file mode 100644 index 000000000..8947b3b63 Binary files /dev/null and b/test/AsmResolver.PE.File.Tests/Resources/HelloWorld.InvalidSectionName.exe differ