From 963c333c2eb8aa33adf30b558ccf6af3986f5abe Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 25 Sep 2025 13:50:51 -0400 Subject: [PATCH] Cache the overlay length --- .../Wrappers/NewExecutable.cs | 82 ++++++++++++++++--- .../Wrappers/PortableExecutable.cs | 82 ++++++++++++++++--- 2 files changed, 138 insertions(+), 26 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/NewExecutable.cs b/SabreTools.Serialization/Wrappers/NewExecutable.cs index aeb1e1a4..88ce3d63 100644 --- a/SabreTools.Serialization/Wrappers/NewExecutable.cs +++ b/SabreTools.Serialization/Wrappers/NewExecutable.cs @@ -129,18 +129,12 @@ namespace SabreTools.Serialization.Wrappers return _overlayData; } - // If a required property is missing - if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null) - { - _overlayData = []; - return _overlayData; - } - - // Get the overlay address if possible + // Get the overlay address and size if possible long endOfSectionData = OverlayAddress; + long overlaySize = OverlaySize; - // If we didn't find the end of section data - if (endOfSectionData <= 0) + // If we didn't find the address or size + if (endOfSectionData <= 0 || overlaySize <= 0) { _overlayData = []; return _overlayData; @@ -154,15 +148,67 @@ namespace SabreTools.Serialization.Wrappers } // Otherwise, cache and return the data - long overlayLength = dataLength - endOfSectionData; - overlayLength = Math.Min(overlayLength, int.MaxValue); + overlaySize = Math.Min(overlaySize, int.MaxValue); - _overlayData = ReadRangeFromSource((int)endOfSectionData, (int)overlayLength); + _overlayData = ReadRangeFromSource((int)endOfSectionData, (int)overlaySize); return _overlayData; } } } + /// + /// Size of the overlay data, if it exists + /// + /// + public long OverlaySize + { + get + { + lock (_overlaySizeLock) + { + // Use the cached data if possible + if (_overlaySize >= 0) + return _overlaySize; + + // Get the available source length, if possible + long dataLength = Length; + if (dataLength == -1) + { + _overlaySize = 0; + return _overlaySize; + } + + // If a required property is missing + if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null) + { + _overlaySize = 0; + return _overlaySize; + } + + // Get the overlay address if possible + long endOfSectionData = OverlayAddress; + + // If we didn't find the end of section data + if (endOfSectionData <= 0) + { + _overlaySize = 0; + return _overlaySize; + } + + // If we're at the end of the file, cache an empty byte array + if (endOfSectionData >= dataLength) + { + _overlaySize = 0; + return _overlaySize; + } + + // Otherwise, cache and return the data + _overlaySize = dataLength - endOfSectionData; + return _overlaySize; + } + } + } + /// /// Overlay strings, if they exist /// @@ -265,6 +311,16 @@ namespace SabreTools.Serialization.Wrappers /// private readonly object _overlayDataLock = new(); + /// + /// Size of the overlay data, if it exists + /// + private long _overlaySize = -1; + + /// + /// Lock object for + /// + private readonly object _overlaySizeLock = new(); + /// /// Overlay strings, if they exist /// diff --git a/SabreTools.Serialization/Wrappers/PortableExecutable.cs b/SabreTools.Serialization/Wrappers/PortableExecutable.cs index f82eee00..f82037e0 100644 --- a/SabreTools.Serialization/Wrappers/PortableExecutable.cs +++ b/SabreTools.Serialization/Wrappers/PortableExecutable.cs @@ -382,18 +382,12 @@ namespace SabreTools.Serialization.Wrappers return _overlayData; } - // If the section table is missing - if (SectionTable == null) - { - _overlayData = []; - return _overlayData; - } - - // Get the overlay address if possible + // Get the overlay address and size if possible long endOfSectionData = OverlayAddress; + long overlaySize = OverlaySize; - // If we didn't find the end of section data - if (endOfSectionData <= 0) + // If we didn't find the address or size + if (endOfSectionData <= 0 || overlaySize <= 0) { _overlayData = []; return _overlayData; @@ -407,15 +401,67 @@ namespace SabreTools.Serialization.Wrappers } // Otherwise, cache and return the data - long overlayLength = dataLength - endOfSectionData; - overlayLength = Math.Min(overlayLength, int.MaxValue); + overlaySize = Math.Min(overlaySize, int.MaxValue); - _overlayData = ReadRangeFromSource(endOfSectionData, (int)overlayLength) ?? []; + _overlayData = ReadRangeFromSource(endOfSectionData, (int)overlaySize) ?? []; return _overlayData; } } } + /// + /// Size of the overlay data, if it exists + /// + /// + public long OverlaySize + { + get + { + lock (_overlaySizeLock) + { + // Use the cached data if possible + if (_overlaySize >= 0) + return _overlaySize; + + // Get the available source length, if possible + long dataLength = Length; + if (dataLength == -1) + { + _overlaySize = 0; + return _overlaySize; + } + + // If the section table is missing + if (SectionTable == null) + { + _overlaySize = 0; + return _overlaySize; + } + + // Get the overlay address if possible + long endOfSectionData = OverlayAddress; + + // If we didn't find the end of section data + if (endOfSectionData <= 0) + { + _overlaySize = 0; + return _overlaySize; + } + + // If we're at the end of the file, cache an empty byte array + if (endOfSectionData >= dataLength) + { + _overlaySize = 0; + return _overlaySize; + } + + // Otherwise, cache and return the length + _overlaySize = dataLength - endOfSectionData; + return _overlaySize; + } + } + } + /// /// Overlay strings, if they exist /// @@ -928,6 +974,16 @@ namespace SabreTools.Serialization.Wrappers /// private readonly object _overlayDataLock = new(); + /// + /// Size of the overlay data, if it exists + /// + private long _overlaySize = -1; + + /// + /// Lock object for + /// + private readonly object _overlaySizeLock = new(); + /// /// Overlay strings, if they exist ///