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);
+ }
}
}