diff --git a/SabreTools.Serialization/Deserializers/PortableExecutable.cs b/SabreTools.Serialization/Deserializers/PortableExecutable.cs index 1012e5df..f8ae2cc4 100644 --- a/SabreTools.Serialization/Deserializers/PortableExecutable.cs +++ b/SabreTools.Serialization/Deserializers/PortableExecutable.cs @@ -302,6 +302,8 @@ namespace SabreTools.Serialization.Deserializers // Read the table data byte[]? tableData = data.ReadFrom(offset, tableSize, retainPosition: true); + if (tableData != null && tableData.Length < optionalHeader.ResourceTable.Size) + Array.Resize(ref tableData, (int)optionalHeader.ResourceTable.Size); // Set the resource directory table long tableStart = data.Position; @@ -309,7 +311,13 @@ namespace SabreTools.Serialization.Deserializers pex.ResourceDirectoryTable = ParseResourceDirectoryTable(tableData, ref tableOffset); // Parse the resource data, if possible - ParseResourceData(tableData, ref tableOffset, offset, pex.ResourceDirectoryTable, pex.SectionTable); + ParseResourceData(data, + initialOffset, + tableData, + ref tableOffset, + offset, + (int)optionalHeader.ResourceTable.Size, + pex.ResourceDirectoryTable, pex.SectionTable); #region Hidden Resources @@ -1560,15 +1568,24 @@ namespace SabreTools.Serialization.Deserializers /// /// Fill in resource data /// - /// Byte array to parse + /// Stream to parse + /// Initial offset to use in address comparisons + /// Byte array to parse /// Offset into the byte array /// Offset to the start of the table + /// Unpadded length of the table /// Resource table to fill in /// Section table to use for virtual address translation /// Filled ResourceDataEntry on success, null on error - public static void ParseResourceData(byte[]? data, ref int dataOffset, long tableStart, ResourceDirectoryTable? table, SectionHeader[] sections) + public static void ParseResourceData(Stream data, + long initialOffset, + byte[]? tableData, + ref int dataOffset, + long tableStart, + long tableLength, + ResourceDirectoryTable? table, SectionHeader[] sections) { - if (data == null) + if (tableData == null) return; if (table?.Entries == null) return; @@ -1578,15 +1595,37 @@ namespace SabreTools.Serialization.Deserializers // Handle directory entries directly if (entry.DataEntry != null && entry.DataEntry.Size > 0) { - // Read the data from the offset - dataOffset = (int)(entry.DataEntry.DataRVA.ConvertVirtualAddress(sections) - tableStart); - if (dataOffset > 0 && dataOffset + entry.DataEntry.Size < data.Length) - entry.DataEntry.Data = data.ReadBytes(ref dataOffset, (int)entry.DataEntry.Size); + // Convert the data RVA to an offset + long nextOffset = entry.DataEntry.DataRVA.ConvertVirtualAddress(sections); + if (nextOffset < 0) + continue; + + // If the offset is within the table data, read from there + if (nextOffset - tableStart + entry.DataEntry.Size <= tableLength) + { + dataOffset = (int)(nextOffset - tableStart); + entry.DataEntry.Data = tableData.ReadBytes(ref dataOffset, (int)entry.DataEntry.Size); + } + + // Otherwise, read from the data stream + else if (nextOffset + entry.DataEntry.Size <= data.Length) + { + entry.DataEntry.Data = data.ReadFrom(nextOffset + initialOffset, (int)entry.DataEntry.Size, retainPosition: true); + } } // Handle subdirectories by recursion else if (entry.Subdirectory != null) - ParseResourceData(data, ref dataOffset, tableStart, entry.Subdirectory, sections); + { + ParseResourceData(data, + initialOffset, + tableData, + ref dataOffset, + tableStart, + tableLength, + entry.Subdirectory, + sections); + } } }