From cd7e6ff98d4f146e0674e8632c01ff761f95b61e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 19 Aug 2025 09:09:33 -0400 Subject: [PATCH] Fix some logic bugs due to offsets --- .../Deserializers/BFPK.cs | 9 +- SabreTools.Serialization/Deserializers/BSP.cs | 5 +- SabreTools.Serialization/Deserializers/CFB.cs | 23 +++-- SabreTools.Serialization/Deserializers/CHD.cs | 9 +- SabreTools.Serialization/Deserializers/GCF.cs | 9 +- .../Deserializers/InstallShieldArchiveV3.cs | 9 +- .../Deserializers/InstallShieldCabinet.cs | 69 ++++++++------- .../Deserializers/LinearExecutable.cs | 86 ++++++++++++------- .../Deserializers/MSDOS.cs | 4 +- .../Deserializers/MicrosoftCabinet.cs | 4 +- .../Deserializers/MoPaQ.cs | 44 +++++----- .../Deserializers/N3DS.cs | 7 +- SabreTools.Serialization/Deserializers/NCF.cs | 9 +- .../Deserializers/NewExecutable.cs | 54 ++++-------- .../Deserializers/Nitro.cs | 13 +-- SabreTools.Serialization/Deserializers/PAK.cs | 7 +- SabreTools.Serialization/Deserializers/PFF.cs | 11 ++- .../Deserializers/PKZIP.cs | 25 +++--- .../Deserializers/PlayJAudio.cs | 27 ++---- .../Deserializers/PlayJPlaylist.cs | 3 +- .../Deserializers/PortableExecutable.cs | 61 +++++++------ SabreTools.Serialization/Deserializers/SGA.cs | 83 ++++++++---------- .../Deserializers/VBSP.cs | 5 +- SabreTools.Serialization/Deserializers/VPK.cs | 25 +++--- .../Deserializers/WAD3.cs | 11 ++- SabreTools.Serialization/Deserializers/XZP.cs | 14 +-- 26 files changed, 339 insertions(+), 287 deletions(-) diff --git a/SabreTools.Serialization/Deserializers/BFPK.cs b/SabreTools.Serialization/Deserializers/BFPK.cs index 8151353c..432484d6 100644 --- a/SabreTools.Serialization/Deserializers/BFPK.cs +++ b/SabreTools.Serialization/Deserializers/BFPK.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new archive to fill var archive = new Archive(); @@ -40,7 +43,7 @@ namespace SabreTools.Serialization.Deserializers // Read all entries in turn for (int i = 0; i < header.Files; i++) { - files[i] = ParseFileEntry(data); + files[i] = ParseFileEntry(data, initialOffset); } // Set the files @@ -62,7 +65,7 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled FileEntry on success, null on error - public static FileEntry ParseFileEntry(Stream data) + public static FileEntry ParseFileEntry(Stream data, long initialOffset) { var fileEntry = new FileEntry(); @@ -78,7 +81,7 @@ namespace SabreTools.Serialization.Deserializers if (fileEntry.Offset > 0) { long currentOffset = data.Position; - data.Seek(fileEntry.Offset, SeekOrigin.Begin); + data.Seek(initialOffset + fileEntry.Offset, SeekOrigin.Begin); fileEntry.CompressedSize = data.ReadInt32LittleEndian(); data.Seek(currentOffset, SeekOrigin.Begin); } diff --git a/SabreTools.Serialization/Deserializers/BSP.cs b/SabreTools.Serialization/Deserializers/BSP.cs index fd9938b9..894f62f4 100644 --- a/SabreTools.Serialization/Deserializers/BSP.cs +++ b/SabreTools.Serialization/Deserializers/BSP.cs @@ -19,6 +19,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life Level to fill var file = new BspFile(); @@ -46,7 +49,7 @@ namespace SabreTools.Serialization.Deserializers continue; // Seek to the lump offset - data.Seek(lumpEntry.Offset, SeekOrigin.Begin); + data.Seek(initialOffset + lumpEntry.Offset, SeekOrigin.Begin); // Read according to the lump type switch ((LumpType)l) diff --git a/SabreTools.Serialization/Deserializers/CFB.cs b/SabreTools.Serialization/Deserializers/CFB.cs index e28a0761..4357c314 100644 --- a/SabreTools.Serialization/Deserializers/CFB.cs +++ b/SabreTools.Serialization/Deserializers/CFB.cs @@ -19,6 +19,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new binary to fill var binary = new Binary(); @@ -62,8 +65,9 @@ namespace SabreTools.Serialization.Deserializers break; // Get the new next sector information - long sectorOffset = (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); - if (sectorOffset < 0 || sectorOffset >= data.Length) + long sectorOffset = initialOffset + + (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); + if (sectorOffset < initialOffset || sectorOffset >= data.Length) return null; // Seek to the next sector @@ -105,8 +109,9 @@ namespace SabreTools.Serialization.Deserializers break; // Get the new next sector information - long sectorOffset = (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); - if (sectorOffset < 0 || sectorOffset >= data.Length) + long sectorOffset = initialOffset + + (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); + if (sectorOffset < initialOffset || sectorOffset >= data.Length) return null; // Seek to the next sector @@ -140,8 +145,9 @@ namespace SabreTools.Serialization.Deserializers break; // Get the new next sector information - long sectorOffset = (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); - if (sectorOffset < 0 || sectorOffset >= data.Length) + long sectorOffset = initialOffset + + (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); + if (sectorOffset < initialOffset || sectorOffset >= data.Length) return null; // Seek to the next sector @@ -194,8 +200,9 @@ namespace SabreTools.Serialization.Deserializers break; // Get the new next sector information - long sectorOffset = (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); - if (sectorOffset < 0 || sectorOffset >= data.Length) + long sectorOffset = initialOffset + + (long)((long)(currentSector + 1) * Math.Pow(2, fileHeader.SectorShift)); + if (sectorOffset < initialOffset || sectorOffset >= data.Length) return null; // Seek to the next sector diff --git a/SabreTools.Serialization/Deserializers/CHD.cs b/SabreTools.Serialization/Deserializers/CHD.cs index aee85e85..2db3d876 100644 --- a/SabreTools.Serialization/Deserializers/CHD.cs +++ b/SabreTools.Serialization/Deserializers/CHD.cs @@ -18,8 +18,11 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Determine the header version - uint version = GetVersion(data); + uint version = GetVersion(data, initialOffset); // Read and return the current CHD switch (version) @@ -98,7 +101,7 @@ namespace SabreTools.Serialization.Deserializers /// Get the matching CHD version, if possible /// /// Matching version, 0 if none - private static uint GetVersion(Stream data) + private static uint GetVersion(Stream data, long initialOffset) { // Read the header values byte[] tagBytes = data.ReadBytes(8); @@ -107,7 +110,7 @@ namespace SabreTools.Serialization.Deserializers uint version = data.ReadUInt32BigEndian(); // Seek back to start - data.SeekIfPossible(); + data.SeekIfPossible(initialOffset); // Check the signature if (!string.Equals(tag, Constants.SignatureString, StringComparison.Ordinal)) diff --git a/SabreTools.Serialization/Deserializers/GCF.cs b/SabreTools.Serialization/Deserializers/GCF.cs index 4c43d320..6a1edb11 100644 --- a/SabreTools.Serialization/Deserializers/GCF.cs +++ b/SabreTools.Serialization/Deserializers/GCF.cs @@ -16,6 +16,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life Game Cache to fill var file = new Models.GCF.File(); @@ -100,7 +103,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Cache the current offset - long initialOffset = data.Position; + long afterMapPosition = data.Position; #region Directory Header @@ -213,7 +216,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Seek to end of directory section, just in case - data.Seek(initialOffset + file.DirectoryHeader.DirectorySize, SeekOrigin.Begin); + data.Seek(afterMapPosition + file.DirectoryHeader.DirectorySize, SeekOrigin.Begin); #region Directory Map Header @@ -301,7 +304,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Seek to end of checksum section, just in case - data.Seek(initialOffset + checksumHeader.ChecksumSize, SeekOrigin.Begin); + data.Seek(afterMapPosition + checksumHeader.ChecksumSize, SeekOrigin.Begin); #region Data Block Header diff --git a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs index 86f01eac..15c54c37 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs @@ -16,6 +16,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new archive to fill var archive = new Archive(); @@ -25,7 +28,7 @@ namespace SabreTools.Serialization.Deserializers var header = ParseHeader(data); if (header.Signature1 != Constants.HeaderSignature) return null; - if (header.TocAddress >= data.Length) + if (initialOffset + header.TocAddress >= data.Length) return null; // Set the archive header @@ -36,8 +39,8 @@ namespace SabreTools.Serialization.Deserializers #region Directories // Get the directories offset - uint directoriesOffset = header.TocAddress; - if (directoriesOffset < 0 || directoriesOffset >= data.Length) + long directoriesOffset = initialOffset + header.TocAddress; + if (directoriesOffset < initialOffset || directoriesOffset >= data.Length) return null; // Seek to the directories diff --git a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs index 9dcfaaf9..c8d99fb7 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs @@ -20,6 +20,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new cabinet to fill var cabinet = new Cabinet(); @@ -48,8 +51,8 @@ namespace SabreTools.Serialization.Deserializers #region Descriptor // Get the descriptor offset - uint descriptorOffset = commonHeader.DescriptorOffset; - if (descriptorOffset < 0 || descriptorOffset >= data.Length) + long descriptorOffset = initialOffset + commonHeader.DescriptorOffset; + if (descriptorOffset < initialOffset || descriptorOffset >= data.Length) return null; // Seek to the descriptor @@ -63,8 +66,8 @@ namespace SabreTools.Serialization.Deserializers #region File Descriptor Offsets // Get the file table offset - uint fileTableOffset = commonHeader.DescriptorOffset + cabinet.Descriptor.FileTableOffset; - if (fileTableOffset < 0 || fileTableOffset >= data.Length) + long fileTableOffset = descriptorOffset + cabinet.Descriptor.FileTableOffset; + if (fileTableOffset < initialOffset || fileTableOffset >= data.Length) return null; // Seek to the file table @@ -93,12 +96,12 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < cabinet.Descriptor.DirectoryCount; i++) { // Get the directory descriptor offset - uint offset = descriptorOffset + long offset = descriptorOffset + cabinet.Descriptor.FileTableOffset + cabinet.FileDescriptorOffsets[i]; // If we have an invalid offset - if (offset < 0 || offset >= data.Length) + if (offset < initialOffset || offset >= data.Length) continue; // Seek to the file descriptor offset @@ -119,7 +122,7 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < cabinet.Descriptor.FileCount; i++) { // Get the file descriptor offset - uint offset; + long offset; if (majorVersion <= 5) { offset = descriptorOffset @@ -135,7 +138,7 @@ namespace SabreTools.Serialization.Deserializers } // If we have an invalid offset - if (offset < 0 || offset >= data.Length) + if (offset < initialOffset || offset >= data.Length) continue; // Seek to the file descriptor offset @@ -156,13 +159,13 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < (cabinet.Descriptor.FileGroupOffsets?.Length ?? 0); i++) { // Get the file group offset - uint offset = cabinet.Descriptor.FileGroupOffsets![i]; + long offset = cabinet.Descriptor.FileGroupOffsets![i]; if (offset == 0) continue; // Adjust the file group offset - offset += commonHeader.DescriptorOffset; - if (offset < 0 || offset >= data.Length) + offset += descriptorOffset; + if (offset < initialOffset || offset >= data.Length) continue; // Seek to the file group offset @@ -173,11 +176,11 @@ namespace SabreTools.Serialization.Deserializers cabinet.FileGroupOffsets[offset] = offsetList; // If we have a nonzero next offset - uint nextOffset = offsetList.NextOffset; + long nextOffset = offsetList.NextOffset; while (nextOffset != 0) { // Get the next offset to read - uint internalOffset = nextOffset + commonHeader.DescriptorOffset; + long internalOffset = descriptorOffset + nextOffset; // Seek to the file group offset data.Seek(internalOffset, SeekOrigin.Begin); @@ -218,7 +221,7 @@ namespace SabreTools.Serialization.Deserializers } /// Seek to the file group - data.Seek(list.DescriptorOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + list.DescriptorOffset, SeekOrigin.Begin); // Add the file group cabinet.FileGroups[fileGroupId++] = ParseFileGroup(data, majorVersion, descriptorOffset); @@ -233,13 +236,13 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < (cabinet.Descriptor.ComponentOffsets?.Length ?? 0); i++) { // Get the component offset - uint offset = cabinet.Descriptor.ComponentOffsets![i]; + long offset = cabinet.Descriptor.ComponentOffsets![i]; if (offset == 0) continue; // Adjust the component offset - offset += commonHeader.DescriptorOffset; - if (offset < 0 || offset >= data.Length) + offset += descriptorOffset; + if (offset < initialOffset || offset >= data.Length) continue; // Seek to the component offset @@ -250,11 +253,11 @@ namespace SabreTools.Serialization.Deserializers cabinet.ComponentOffsets[cabinet.Descriptor.ComponentOffsets[i]] = offsetList; // If we have a nonzero next offset - uint nextOffset = offsetList.NextOffset; + long nextOffset = offsetList.NextOffset; while (nextOffset != 0) { // Get the next offset to read - uint internalOffset = nextOffset + commonHeader.DescriptorOffset; + long internalOffset = descriptorOffset + nextOffset; // Seek to the file group offset data.Seek(internalOffset, SeekOrigin.Begin); @@ -295,7 +298,7 @@ namespace SabreTools.Serialization.Deserializers } // Seek to the component - data.Seek(list.DescriptorOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + list.DescriptorOffset, SeekOrigin.Begin); // Add the component cabinet.Components[componentId++] = ParseComponent(data, majorVersion, descriptorOffset); @@ -340,7 +343,7 @@ namespace SabreTools.Serialization.Deserializers /// Major version of the cabinet /// Offset of the cabinet descriptor /// Filled Component on success, null on error - public static Component ParseComponent(Stream data, int majorVersion, uint descriptorOffset) + public static Component ParseComponent(Stream data, int majorVersion, long descriptorOffset) { var obj = new Component(); @@ -384,7 +387,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.IdentifierOffset != 0) { // Seek to the identifier - data.Seek(obj.IdentifierOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.IdentifierOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) @@ -397,7 +400,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.DisplayNameOffset != 0) { // Seek to the name - data.Seek(obj.DisplayNameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.DisplayNameOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) @@ -410,7 +413,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.NameOffset != 0) { // Seek to the name - data.Seek(obj.NameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.NameOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) @@ -423,7 +426,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.CLSIDOffset != 0) { // Seek to the CLSID - data.Seek(obj.CLSIDOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.CLSIDOffset, SeekOrigin.Begin); // Read the GUID obj.CLSID = data.ReadGuid(); @@ -433,7 +436,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.FileGroupCount != 0 && obj.FileGroupNamesOffset != 0) { // Seek to the file group table offset - data.Seek(obj.FileGroupNamesOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.FileGroupNamesOffset, SeekOrigin.Begin); // Read the file group names table obj.FileGroupNames = new string[obj.FileGroupCount]; @@ -446,7 +449,7 @@ namespace SabreTools.Serialization.Deserializers long preNameOffset = data.Position; // Seek to the name offset - data.Seek(nameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + nameOffset, SeekOrigin.Begin); if (majorVersion >= 17) obj.FileGroupNames[j] = data.ReadNullTerminatedUnicodeString() ?? string.Empty; @@ -530,7 +533,7 @@ namespace SabreTools.Serialization.Deserializers /// Major version of the cabinet /// Offset of the cabinet descriptor /// Filled FileDescriptor on success, null on error - public static FileDescriptor ParseFileDescriptor(Stream data, int majorVersion, uint descriptorOffset) + public static FileDescriptor ParseFileDescriptor(Stream data, int majorVersion, long descriptorOffset) { var obj = new FileDescriptor(); @@ -573,7 +576,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.NameOffset != 0) { // Seek to the name - data.Seek(obj.NameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.NameOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) @@ -595,7 +598,7 @@ namespace SabreTools.Serialization.Deserializers /// Major version of the cabinet /// Offset of the cabinet descriptor /// Filled FileGroup on success, null on error - public static FileGroup ParseFileGroup(Stream data, int majorVersion, uint descriptorOffset) + public static FileGroup ParseFileGroup(Stream data, int majorVersion, long descriptorOffset) { var obj = new FileGroup(); @@ -631,7 +634,7 @@ namespace SabreTools.Serialization.Deserializers if (obj.NameOffset != 0) { // Seek to the name - data.Seek(obj.NameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.NameOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) @@ -653,7 +656,7 @@ namespace SabreTools.Serialization.Deserializers /// Major version of the cabinet /// Offset of the cabinet descriptor /// Filled OffsetList on success, null on error - public static OffsetList ParseOffsetList(Stream data, int majorVersion, uint descriptorOffset) + public static OffsetList ParseOffsetList(Stream data, int majorVersion, long descriptorOffset) { var obj = new OffsetList(); @@ -665,7 +668,7 @@ namespace SabreTools.Serialization.Deserializers long currentOffset = data.Position; // Seek to the name offset - data.Seek(obj.NameOffset + descriptorOffset, SeekOrigin.Begin); + data.Seek(descriptorOffset + obj.NameOffset, SeekOrigin.Begin); // Read the string if (majorVersion >= 17) diff --git a/SabreTools.Serialization/Deserializers/LinearExecutable.cs b/SabreTools.Serialization/Deserializers/LinearExecutable.cs index d5a019a1..e9a47460 100644 --- a/SabreTools.Serialization/Deserializers/LinearExecutable.cs +++ b/SabreTools.Serialization/Deserializers/LinearExecutable.cs @@ -19,7 +19,7 @@ namespace SabreTools.Serialization.Deserializers try { // Cache the current offset - int initialOffset = (int)data.Position; + long initialOffset = data.Position; // Create a new executable to fill var executable = new Executable(); @@ -52,8 +52,10 @@ namespace SabreTools.Serialization.Deserializers #region Object Table // Get the object table offset - long offset = informationBlock.ObjectTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + long offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ObjectTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the object table data.Seek(offset, SeekOrigin.Begin); @@ -73,8 +75,10 @@ namespace SabreTools.Serialization.Deserializers #region Object Page Map // Get the object page map offset - offset = informationBlock.ObjectPageMapOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ObjectPageMapOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the object page map data.Seek(offset, SeekOrigin.Begin); @@ -93,8 +97,10 @@ namespace SabreTools.Serialization.Deserializers #region Object Iterate Data Map - offset = informationBlock.ObjectIterateDataMapOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ObjectIterateDataMapOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the object page map data.Seek(offset, SeekOrigin.Begin); @@ -109,8 +115,10 @@ namespace SabreTools.Serialization.Deserializers #region Resource Table // Get the resource table offset - offset = informationBlock.ResourceTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ResourceTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the resource table data.Seek(offset, SeekOrigin.Begin); @@ -130,8 +138,10 @@ namespace SabreTools.Serialization.Deserializers #region Resident Names Table // Get the resident names table offset - offset = informationBlock.ResidentNamesTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ResidentNamesTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the resident names table data.Seek(offset, SeekOrigin.Begin); @@ -159,8 +169,10 @@ namespace SabreTools.Serialization.Deserializers #region Entry Table // Get the entry table offset - offset = informationBlock.EntryTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.EntryTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the entry table data.Seek(offset, SeekOrigin.Begin); @@ -189,8 +201,10 @@ namespace SabreTools.Serialization.Deserializers #region Module Format Directives Table // Get the module format directives table offset - offset = informationBlock.ModuleDirectivesTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ModuleDirectivesTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the module format directives table data.Seek(offset, SeekOrigin.Begin); @@ -218,8 +232,10 @@ namespace SabreTools.Serialization.Deserializers #region Fix-up Page Table // Get the fix-up page table offset - offset = informationBlock.FixupPageTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.FixupPageTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the fix-up page table data.Seek(offset, SeekOrigin.Begin); @@ -239,8 +255,10 @@ namespace SabreTools.Serialization.Deserializers #region Fix-up Record Table // Get the fix-up record table offset - offset = informationBlock.FixupRecordTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.FixupRecordTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the fix-up record table data.Seek(offset, SeekOrigin.Begin); @@ -264,8 +282,10 @@ namespace SabreTools.Serialization.Deserializers #region Imported Module Name Table // Get the imported module name table offset - offset = informationBlock.ImportedModulesNameTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ImportedModulesNameTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the imported module name table data.Seek(offset, SeekOrigin.Begin); @@ -285,8 +305,10 @@ namespace SabreTools.Serialization.Deserializers #region Imported Module Procedure Name Table // Get the imported module procedure name table offset - offset = informationBlock.ImportProcedureNameTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.ImportProcedureNameTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the imported module procedure name table data.Seek(offset, SeekOrigin.Begin); @@ -315,8 +337,10 @@ namespace SabreTools.Serialization.Deserializers #region Per-Page Checksum Table // Get the per-page checksum table offset - offset = informationBlock.PerPageChecksumTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.PerPageChecksumTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the per-page checksum name table data.Seek(offset, SeekOrigin.Begin); @@ -336,8 +360,10 @@ namespace SabreTools.Serialization.Deserializers #region Non-Resident Names Table // Get the non-resident names table offset - offset = informationBlock.NonResidentNamesTableOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.NonResidentNamesTableOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the non-resident names table data.Seek(offset, SeekOrigin.Begin); @@ -365,8 +391,10 @@ namespace SabreTools.Serialization.Deserializers #region Debug Information // Get the debug information offset - offset = informationBlock.DebugInformationOffset + stub.Header.NewExeHeaderAddr; - if (offset > stub.Header.NewExeHeaderAddr && offset < data.Length) + offset = initialOffset + + stub.Header.NewExeHeaderAddr + + informationBlock.DebugInformationOffset; + if (offset > initialOffset + stub.Header.NewExeHeaderAddr && offset < data.Length) { // Seek to the debug information data.Seek(offset, SeekOrigin.Begin); diff --git a/SabreTools.Serialization/Deserializers/MSDOS.cs b/SabreTools.Serialization/Deserializers/MSDOS.cs index 46001a5a..b026a24a 100644 --- a/SabreTools.Serialization/Deserializers/MSDOS.cs +++ b/SabreTools.Serialization/Deserializers/MSDOS.cs @@ -18,7 +18,7 @@ namespace SabreTools.Serialization.Deserializers try { // Cache the current offset - int initialOffset = (int)data.Position; + long initialOffset = data.Position; // Create a new executable to fill var executable = new Executable(); @@ -38,7 +38,7 @@ namespace SabreTools.Serialization.Deserializers #region Relocation Table // If the offset for the relocation table doesn't exist - int tableAddress = initialOffset + executableHeader.RelocationTableAddr; + long tableAddress = initialOffset + executableHeader.RelocationTableAddr; if (tableAddress >= data.Length) return executable; diff --git a/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs b/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs index 04685a15..22420c43 100644 --- a/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs @@ -19,7 +19,7 @@ namespace SabreTools.Serialization.Deserializers try { // Cache the current offset - int initialOffset = (int)data.Position; + long initialOffset = data.Position; // Create a new cabinet to fill var cabinet = new Cabinet(); @@ -57,7 +57,7 @@ namespace SabreTools.Serialization.Deserializers #region Files // Get the files offset - int filesOffset = (int)cabinetHeader.FilesOffset + initialOffset; + long filesOffset = initialOffset + cabinetHeader.FilesOffset; if (filesOffset > data.Length) return null; diff --git a/SabreTools.Serialization/Deserializers/MoPaQ.cs b/SabreTools.Serialization/Deserializers/MoPaQ.cs index 535333a9..9445133a 100644 --- a/SabreTools.Serialization/Deserializers/MoPaQ.cs +++ b/SabreTools.Serialization/Deserializers/MoPaQ.cs @@ -19,6 +19,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new archive to fill var archive = new Archive(); @@ -29,9 +32,6 @@ namespace SabreTools.Serialization.Deserializers data.Seek(-4, SeekOrigin.Current); if (possibleSignature == UserDataSignatureUInt32) { - // Save the current position for offset correction - long basePtr = data.Position; - // Deserialize the user data, returning null if invalid var userData = ParseUserData(data); if (userData?.Signature != UserDataSignatureString) @@ -41,7 +41,7 @@ namespace SabreTools.Serialization.Deserializers archive.UserData = userData; // Set the starting position according to the header offset - data.Seek(basePtr + (int)archive.UserData.HeaderOffset, SeekOrigin.Begin); + data.Seek(initialOffset + archive.UserData.HeaderOffset, SeekOrigin.Begin); } #endregion @@ -76,8 +76,8 @@ namespace SabreTools.Serialization.Deserializers if (archive.ArchiveHeader.FormatVersion == FormatVersion.Format1) { // If we have a hash table - long hashTableOffset = archive.ArchiveHeader.HashTablePosition; - if (hashTableOffset != 0) + long hashTableOffset = initialOffset + archive.ArchiveHeader.HashTablePosition; + if (hashTableOffset > initialOffset) { // Seek to the offset data.Seek(hashTableOffset, SeekOrigin.Begin); @@ -103,8 +103,8 @@ namespace SabreTools.Serialization.Deserializers || archive.ArchiveHeader.FormatVersion == FormatVersion.Format3) { // If we have a hash table - long hashTableOffset = ((uint)archive.ArchiveHeader.HashTablePositionHi << 23) | archive.ArchiveHeader.HashTablePosition; - if (hashTableOffset != 0) + long hashTableOffset = initialOffset + (((uint)archive.ArchiveHeader.HashTablePositionHi << 23) | archive.ArchiveHeader.HashTablePosition); + if (hashTableOffset > initialOffset) { // Seek to the offset data.Seek(hashTableOffset, SeekOrigin.Begin); @@ -129,8 +129,8 @@ namespace SabreTools.Serialization.Deserializers else if (archive.ArchiveHeader.FormatVersion == FormatVersion.Format4) { // If we have a hash table - long hashTableOffset = ((uint)archive.ArchiveHeader.HashTablePositionHi << 23) | archive.ArchiveHeader.HashTablePosition; - if (hashTableOffset != 0) + long hashTableOffset = initialOffset + (((uint)archive.ArchiveHeader.HashTablePositionHi << 23) | archive.ArchiveHeader.HashTablePosition); + if (hashTableOffset > initialOffset) { // Seek to the offset data.Seek(hashTableOffset, SeekOrigin.Begin); @@ -159,8 +159,8 @@ namespace SabreTools.Serialization.Deserializers if (archive.ArchiveHeader.FormatVersion == FormatVersion.Format1) { // If we have a block table - long blockTableOffset = archive.ArchiveHeader.BlockTablePosition; - if (blockTableOffset != 0) + long blockTableOffset = initialOffset + archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset > initialOffset) { // Seek to the offset data.Seek(blockTableOffset, SeekOrigin.Begin); @@ -186,8 +186,8 @@ namespace SabreTools.Serialization.Deserializers || archive.ArchiveHeader.FormatVersion == FormatVersion.Format3) { // If we have a block table - long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; - if (blockTableOffset != 0) + long blockTableOffset = initialOffset + (((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition); + if (blockTableOffset > initialOffset) { // Seek to the offset data.Seek(blockTableOffset, SeekOrigin.Begin); @@ -212,8 +212,8 @@ namespace SabreTools.Serialization.Deserializers else if (archive.ArchiveHeader.FormatVersion == FormatVersion.Format4) { // If we have a block table - long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; - if (blockTableOffset != 0) + long blockTableOffset = initialOffset + (((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition); + if (blockTableOffset > initialOffset) { // Seek to the offset data.Seek(blockTableOffset, SeekOrigin.Begin); @@ -242,8 +242,8 @@ namespace SabreTools.Serialization.Deserializers if (archive.ArchiveHeader.FormatVersion >= FormatVersion.Format2) { // If we have a hi-block table - long hiBlockTableOffset = (long)archive.ArchiveHeader.HiBlockTablePosition; - if (hiBlockTableOffset != 0) + long hiBlockTableOffset = initialOffset + (long)archive.ArchiveHeader.HiBlockTablePosition; + if (hiBlockTableOffset > initialOffset) { // Seek to the offset data.Seek(hiBlockTableOffset, SeekOrigin.Begin); @@ -269,8 +269,8 @@ namespace SabreTools.Serialization.Deserializers if (archive.ArchiveHeader.FormatVersion >= FormatVersion.Format3) { // If we have a BET table - long betTableOffset = (long)archive.ArchiveHeader.BetTablePosition; - if (betTableOffset != 0) + long betTableOffset = initialOffset + (long)archive.ArchiveHeader.BetTablePosition; + if (betTableOffset > initialOffset) { // Seek to the offset data.Seek(betTableOffset, SeekOrigin.Begin); @@ -292,8 +292,8 @@ namespace SabreTools.Serialization.Deserializers if (archive.ArchiveHeader.FormatVersion >= FormatVersion.Format3) { // If we have a HET table - long hetTableOffset = (long)archive.ArchiveHeader.HetTablePosition; - if (hetTableOffset != 0) + long hetTableOffset = initialOffset + (long)archive.ArchiveHeader.HetTablePosition; + if (hetTableOffset > initialOffset) { // Seek to the offset data.Seek(hetTableOffset, SeekOrigin.Begin); diff --git a/SabreTools.Serialization/Deserializers/N3DS.cs b/SabreTools.Serialization/Deserializers/N3DS.cs index 6943c449..3926657a 100644 --- a/SabreTools.Serialization/Deserializers/N3DS.cs +++ b/SabreTools.Serialization/Deserializers/N3DS.cs @@ -18,6 +18,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new cart image to fill var cart = new Cart(); @@ -64,9 +67,9 @@ namespace SabreTools.Serialization.Deserializers for (int i = 0; i < 8; i++) { // Find the offset to the partition - long partitionOffset = cart.Header.PartitionsTable?[i]?.Offset ?? 0; + long partitionOffset = initialOffset + cart.Header.PartitionsTable?[i]?.Offset ?? 0; partitionOffset *= mediaUnitSize; - if (partitionOffset == 0) + if (partitionOffset <= initialOffset) continue; // Seek to the start of the partition diff --git a/SabreTools.Serialization/Deserializers/NCF.cs b/SabreTools.Serialization/Deserializers/NCF.cs index e63c83e2..ff67a165 100644 --- a/SabreTools.Serialization/Deserializers/NCF.cs +++ b/SabreTools.Serialization/Deserializers/NCF.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life No Cache to fill var file = new Models.NCF.File(); @@ -37,7 +40,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Cache the current offset - long initialOffset = data.Position; + long afterHeaderPosition = data.Position; #region Directory Header @@ -148,7 +151,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Seek to end of directory section, just in case - data.Seek(initialOffset + directoryHeader.DirectorySize, SeekOrigin.Begin); + data.Seek(afterHeaderPosition + directoryHeader.DirectorySize, SeekOrigin.Begin); #region Unknown Header @@ -233,7 +236,7 @@ namespace SabreTools.Serialization.Deserializers #endregion // Seek to end of checksum section, just in case - data.Seek(initialOffset + checksumHeader.ChecksumSize, SeekOrigin.Begin); + data.Seek(afterHeaderPosition + checksumHeader.ChecksumSize, SeekOrigin.Begin); return file; } diff --git a/SabreTools.Serialization/Deserializers/NewExecutable.cs b/SabreTools.Serialization/Deserializers/NewExecutable.cs index 20f639e1..28dbe005 100644 --- a/SabreTools.Serialization/Deserializers/NewExecutable.cs +++ b/SabreTools.Serialization/Deserializers/NewExecutable.cs @@ -20,7 +20,7 @@ namespace SabreTools.Serialization.Deserializers try { // Cache the current offset - int initialOffset = (int)data.Position; + long initialOffset = data.Position; // Create a new executable to fill var executable = new Executable(); @@ -53,9 +53,7 @@ namespace SabreTools.Serialization.Deserializers #region Segment Table // If the offset for the segment table doesn't exist - int tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.SegmentTableOffset; + long tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.SegmentTableOffset; if (tableAddress >= data.Length) return executable; @@ -74,9 +72,7 @@ namespace SabreTools.Serialization.Deserializers #region Resource Table // If the offset for the segment table doesn't exist - tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.ResourceTableOffset; + tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.ResourceTableOffset; if (tableAddress >= data.Length) return executable; @@ -91,12 +87,8 @@ namespace SabreTools.Serialization.Deserializers #region Resident-Name Table // If the offset for the resident-name table doesn't exist - tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.ResidentNameTableOffset; - int endOffset = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.ModuleReferenceTableOffset; + tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.ResidentNameTableOffset; + long endOffset = initialOffset + stub.Header.NewExeHeaderAddr + header.ModuleReferenceTableOffset; if (tableAddress >= data.Length) return executable; @@ -111,9 +103,7 @@ namespace SabreTools.Serialization.Deserializers #region Module-Reference Table // If the offset for the module-reference table doesn't exist - tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.ModuleReferenceTableOffset; + tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.ModuleReferenceTableOffset; if (tableAddress >= data.Length) return executable; @@ -132,12 +122,8 @@ namespace SabreTools.Serialization.Deserializers #region Imported-Name Table // If the offset for the imported-name table doesn't exist - tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.ImportedNamesTableOffset; - endOffset = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.EntryTableOffset; + tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.ImportedNamesTableOffset; + endOffset = initialOffset + stub.Header.NewExeHeaderAddr + header.EntryTableOffset; if (tableAddress >= data.Length) return executable; @@ -152,13 +138,8 @@ namespace SabreTools.Serialization.Deserializers #region Entry Table // If the offset for the imported-name table doesn't exist - tableAddress = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.EntryTableOffset; - endOffset = initialOffset - + (int)stub.Header.NewExeHeaderAddr - + header.EntryTableOffset - + header.EntryTableSize; + tableAddress = initialOffset + stub.Header.NewExeHeaderAddr + header.EntryTableOffset; + endOffset = initialOffset + stub.Header.NewExeHeaderAddr + + header.EntryTableOffset + header.EntryTableSize; if (tableAddress >= data.Length) return executable; @@ -173,11 +154,8 @@ namespace SabreTools.Serialization.Deserializers #region Nonresident-Name Table // If the offset for the nonresident-name table doesn't exist - tableAddress = initialOffset - + (int)header.NonResidentNamesTableOffset; - endOffset = initialOffset - + (int)header.NonResidentNamesTableOffset - + header.NonResidentNameTableSize; + tableAddress = initialOffset + header.NonResidentNamesTableOffset; + endOffset = initialOffset + header.NonResidentNamesTableOffset + header.NonResidentNameTableSize; if (tableAddress >= data.Length) return executable; @@ -204,7 +182,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// First address not part of the entry table /// Filled entry table on success, null on error - public static EntryTableBundle[] ParseEntryTable(Stream data, int endOffset) + public static EntryTableBundle[] ParseEntryTable(Stream data, long endOffset) { var entryTable = new List(); @@ -287,7 +265,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// First address not part of the imported-name table /// Filled imported-name table on success, null on error - public static Dictionary ParseImportedNameTable(Stream data, int endOffset) + public static Dictionary ParseImportedNameTable(Stream data, long endOffset) { var importedNameTable = new Dictionary(); @@ -381,7 +359,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// First address not part of the nonresident-name table /// Filled nonresident-name table on success, null on error - public static NonResidentNameTableEntry[] ParseNonResidentNameTable(Stream data, int endOffset) + public static NonResidentNameTableEntry[] ParseNonResidentNameTable(Stream data, long endOffset) { var residentNameTable = new List(); @@ -482,7 +460,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// First address not part of the resident-name table /// Filled resident-name table on success, null on error - public static ResidentNameTableEntry[] ParseResidentNameTable(Stream data, int endOffset) + public static ResidentNameTableEntry[] ParseResidentNameTable(Stream data, long endOffset) { var residentNameTable = new List(); diff --git a/SabreTools.Serialization/Deserializers/Nitro.cs b/SabreTools.Serialization/Deserializers/Nitro.cs index 767802f5..839c35cd 100644 --- a/SabreTools.Serialization/Deserializers/Nitro.cs +++ b/SabreTools.Serialization/Deserializers/Nitro.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new cart image to fill var cart = new Cart(); @@ -38,7 +41,7 @@ namespace SabreTools.Serialization.Deserializers #region Secure Area // Try to get the secure area offset - long secureAreaOffset = 0x4000; + long secureAreaOffset = initialOffset + 0x4000; if (secureAreaOffset > data.Length) return null; @@ -53,8 +56,8 @@ namespace SabreTools.Serialization.Deserializers #region Name Table // Try to get the name table offset - long nameTableOffset = cart.CommonHeader.FileNameTableOffset; - if (nameTableOffset < 0 || nameTableOffset > data.Length) + long nameTableOffset = initialOffset + cart.CommonHeader.FileNameTableOffset; + if (nameTableOffset < initialOffset || nameTableOffset > data.Length) return null; // Seek to the name table @@ -68,8 +71,8 @@ namespace SabreTools.Serialization.Deserializers #region File Allocation Table // Try to get the file allocation table offset - long fileAllocationTableOffset = cart.CommonHeader.FileAllocationTableOffset; - if (fileAllocationTableOffset < 0 || fileAllocationTableOffset > data.Length) + long fileAllocationTableOffset = initialOffset + cart.CommonHeader.FileAllocationTableOffset; + if (fileAllocationTableOffset < initialOffset || fileAllocationTableOffset > data.Length) return null; // Seek to the file allocation table diff --git a/SabreTools.Serialization/Deserializers/PAK.cs b/SabreTools.Serialization/Deserializers/PAK.cs index 69bc078b..2cf3a19e 100644 --- a/SabreTools.Serialization/Deserializers/PAK.cs +++ b/SabreTools.Serialization/Deserializers/PAK.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life Package to fill var file = new Models.PAK.File(); @@ -35,8 +38,8 @@ namespace SabreTools.Serialization.Deserializers #region Directory Items // Get the directory items offset - uint directoryItemsOffset = header.DirectoryOffset; - if (directoryItemsOffset < 0 || directoryItemsOffset >= data.Length) + long directoryItemsOffset = initialOffset + header.DirectoryOffset; + if (directoryItemsOffset < initialOffset || directoryItemsOffset >= data.Length) return null; // Seek to the directory items diff --git a/SabreTools.Serialization/Deserializers/PFF.cs b/SabreTools.Serialization/Deserializers/PFF.cs index c2fa6eff..6d845597 100644 --- a/SabreTools.Serialization/Deserializers/PFF.cs +++ b/SabreTools.Serialization/Deserializers/PFF.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new archive to fill var archive = new Archive(); @@ -60,8 +63,8 @@ namespace SabreTools.Serialization.Deserializers #region Segments // Get the segments - long offset = header.FileListOffset; - if (offset < 0 || offset >= data.Length) + long offset = initialOffset + header.FileListOffset; + if (offset < initialOffset || offset >= data.Length) return null; // Seek to the segments @@ -81,8 +84,8 @@ namespace SabreTools.Serialization.Deserializers #region Footer // Get the footer offset - offset = header.FileListOffset + (header.FileSegmentSize * header.NumberOfFiles); - if (offset < 0 || offset >= data.Length) + offset = initialOffset + header.FileListOffset + (header.FileSegmentSize * header.NumberOfFiles); + if (offset < initialOffset || offset >= data.Length) return null; // Seek to the footer diff --git a/SabreTools.Serialization/Deserializers/PKZIP.cs b/SabreTools.Serialization/Deserializers/PKZIP.cs index 2b971ce0..57fa4c88 100644 --- a/SabreTools.Serialization/Deserializers/PKZIP.cs +++ b/SabreTools.Serialization/Deserializers/PKZIP.cs @@ -23,13 +23,16 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + var archive = new Archive(); #region End of Central Directory Record // Find the end of central directory record long eocdrOffset = SearchForEndOfCentralDirectoryRecord(data); - if (eocdrOffset < 0 || eocdrOffset >= data.Length) + if (eocdrOffset < initialOffset || eocdrOffset >= data.Length) return null; // Seek to the end of central directory record @@ -63,7 +66,7 @@ namespace SabreTools.Serialization.Deserializers // Find the ZIP64 end of central directory locator long eocdlOffset = SearchForZIP64EndOfCentralDirectoryLocator(data); - if (eocdlOffset < 0 || eocdlOffset >= data.Length) + if (eocdlOffset < initialOffset || eocdlOffset >= data.Length) return null; // Seek to the ZIP64 end of central directory locator @@ -78,11 +81,11 @@ namespace SabreTools.Serialization.Deserializers archive.ZIP64EndOfCentralDirectoryLocator = eocdl64; // Try to get the ZIP64 end of central directory record offset - if ((long)eocdl64.CentralDirectoryOffset < 0 || (long)eocdl64.CentralDirectoryOffset >= data.Length) + if ((long)eocdl64.CentralDirectoryOffset < 0 || initialOffset + (long)eocdl64.CentralDirectoryOffset >= data.Length) return null; // Seek to the ZIP64 end of central directory record - data.Seek((long)eocdl64.CentralDirectoryOffset, SeekOrigin.Begin); + data.Seek(initialOffset + (long)eocdl64.CentralDirectoryOffset, SeekOrigin.Begin); // Read the ZIP64 end of central directory record var eocdr64 = ParseEndOfCentralDirectoryRecord64(data); @@ -101,12 +104,12 @@ namespace SabreTools.Serialization.Deserializers long cdrOffset, cdrSize; if (zip64 && archive.ZIP64EndOfCentralDirectoryRecord != null) { - cdrOffset = (long)archive.ZIP64EndOfCentralDirectoryRecord.CentralDirectoryOffset; + cdrOffset = initialOffset + (long)archive.ZIP64EndOfCentralDirectoryRecord.CentralDirectoryOffset; cdrSize = (long)archive.ZIP64EndOfCentralDirectoryRecord.CentralDirectorySize; } else if (archive.EndOfCentralDirectoryRecord != null) { - cdrOffset = archive.EndOfCentralDirectoryRecord.CentralDirectoryOffset; + cdrOffset = initialOffset + archive.EndOfCentralDirectoryRecord.CentralDirectoryOffset; cdrSize = archive.EndOfCentralDirectoryRecord.CentralDirectorySize; } else @@ -115,7 +118,7 @@ namespace SabreTools.Serialization.Deserializers } // Try to get the central directory record offset - if (cdrOffset < 0 || cdrOffset >= data.Length) + if (cdrOffset < initialOffset || cdrOffset >= data.Length) return null; // Seek to the first central directory record @@ -188,11 +191,11 @@ namespace SabreTools.Serialization.Deserializers headerOffset = BitConverter.ToInt64(extraData, 4); } - if (headerOffset < 0 || headerOffset >= data.Length) + if (headerOffset < 0 || initialOffset + headerOffset >= data.Length) return null; // Seek to the local file header - data.Seek(headerOffset, SeekOrigin.Begin); + data.Seek(initialOffset + headerOffset, SeekOrigin.Begin); // Try to parse the local header var localFileHeader = ParseLocalFileHeader(data); @@ -212,7 +215,7 @@ namespace SabreTools.Serialization.Deserializers // Only read the encryption header if necessary #if NET20 || NET35 - if ((header.Flags & GeneralPurposeBitFlags.FileEncrypted) != 0) + if ((header.Flags & GeneralPurposeBitFlags.FileEncrypted) != 0) #else if (header.Flags.HasFlag(GeneralPurposeBitFlags.FileEncrypted)) #endif @@ -241,7 +244,7 @@ namespace SabreTools.Serialization.Deserializers // Only read the data descriptor if necessary #if NET20 || NET35 - if ((header.Flags & GeneralPurposeBitFlags.NoCRC) != 0) + if ((header.Flags & GeneralPurposeBitFlags.NoCRC) != 0) #else if (header.Flags.HasFlag(GeneralPurposeBitFlags.NoCRC)) #endif diff --git a/SabreTools.Serialization/Deserializers/PlayJAudio.cs b/SabreTools.Serialization/Deserializers/PlayJAudio.cs index d34b98ac..7df645dc 100644 --- a/SabreTools.Serialization/Deserializers/PlayJAudio.cs +++ b/SabreTools.Serialization/Deserializers/PlayJAudio.cs @@ -8,20 +8,8 @@ namespace SabreTools.Serialization.Deserializers { public class PlayJAudio : BaseBinaryDeserializer { - /// - public static AudioFile? DeserializeStream(Stream? data, long adjust = 0) - { - var deserializer = new PlayJAudio(); - return deserializer.Deserialize(data, adjust); - } - /// public override AudioFile? Deserialize(Stream? data) - => Deserialize(data, 0); - - /// - /// Offset to adjust all seeking by - public AudioFile? Deserialize(Stream? data, long adjust) { // If the data is invalid if (data == null || !data.CanRead) @@ -29,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new audio file to fill var audioFile = new AudioFile(); @@ -54,8 +45,8 @@ namespace SabreTools.Serialization.Deserializers if (unknownOffset1 > 0) { // Get the unknown block 1 offset - long offset = unknownOffset1 + adjust; - if (offset < 0 || offset >= data.Length) + long offset = initialOffset + unknownOffset1; + if (offset < initialOffset || offset >= data.Length) return null; // Seek to the unknown block 1 @@ -86,8 +77,8 @@ namespace SabreTools.Serialization.Deserializers if (unknownOffset2 != null && unknownOffset2 > 0) { // Get the unknown value 2 offset - long offset = unknownOffset2.Value + adjust; - if (offset < 0 || offset >= data.Length) + long offset = initialOffset + unknownOffset2.Value; + if (offset < initialOffset || offset >= data.Length) return null; // Seek to the unknown value 2 @@ -108,8 +99,8 @@ namespace SabreTools.Serialization.Deserializers if (unknownOffset3 != null && unknownOffset3 > 0) { // Get the unknown block 3 offset - long offset = unknownOffset3.Value + adjust; - if (offset < 0 || offset >= data.Length) + long offset = initialOffset + unknownOffset3.Value; + if (offset < initialOffset || offset >= data.Length) return null; // Seek to the unknown block 3 diff --git a/SabreTools.Serialization/Deserializers/PlayJPlaylist.cs b/SabreTools.Serialization/Deserializers/PlayJPlaylist.cs index 9102ee35..ebc393e5 100644 --- a/SabreTools.Serialization/Deserializers/PlayJPlaylist.cs +++ b/SabreTools.Serialization/Deserializers/PlayJPlaylist.cs @@ -38,8 +38,7 @@ namespace SabreTools.Serialization.Deserializers // Try to parse the audio files for (int i = 0; i < playlist.AudioFiles.Length; i++) { - long currentOffset = data.Position; - var entryHeader = PlayJAudio.DeserializeStream(data, currentOffset); + var entryHeader = PlayJAudio.DeserializeStream(data); if (entryHeader == null) continue; diff --git a/SabreTools.Serialization/Deserializers/PortableExecutable.cs b/SabreTools.Serialization/Deserializers/PortableExecutable.cs index 906511dc..21cf94df 100644 --- a/SabreTools.Serialization/Deserializers/PortableExecutable.cs +++ b/SabreTools.Serialization/Deserializers/PortableExecutable.cs @@ -90,7 +90,7 @@ namespace SabreTools.Serialization.Deserializers // TODO: Validate that this is correct with an "old" PE long symbolTableAddress = initialOffset + coffFileHeader.PointerToSymbolTable; - if (symbolTableAddress != 0 && symbolTableAddress < data.Length) + if (symbolTableAddress > initialOffset && symbolTableAddress < data.Length) { // Seek to the COFF symbol table data.Seek(symbolTableAddress, SeekOrigin.Begin); @@ -112,13 +112,13 @@ namespace SabreTools.Serialization.Deserializers { long exportTableAddress = initialOffset + optionalHeader.ExportTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (exportTableAddress != 0 && exportTableAddress < data.Length) + if (exportTableAddress > initialOffset && exportTableAddress < data.Length) { // Seek to the export table data.Seek(exportTableAddress, SeekOrigin.Begin); // Set the export table - executable.ExportTable = ParseExportTable(data, executable.SectionTable); + executable.ExportTable = ParseExportTable(data, initialOffset, executable.SectionTable); } } @@ -131,13 +131,13 @@ namespace SabreTools.Serialization.Deserializers { long importTableAddress = initialOffset + optionalHeader.ImportTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (importTableAddress != 0 && importTableAddress < data.Length) + if (importTableAddress > initialOffset && importTableAddress < data.Length) { // Seek to the import table data.Seek(importTableAddress, SeekOrigin.Begin); // Set the import table - executable.ImportTable = ParseImportTable(data, optionalHeader.Magic, executable.SectionTable); + executable.ImportTable = ParseImportTable(data, initialOffset, optionalHeader.Magic, executable.SectionTable); } } @@ -150,7 +150,7 @@ namespace SabreTools.Serialization.Deserializers { long resourceTableAddress = initialOffset + optionalHeader.ResourceTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (resourceTableAddress != 0 && resourceTableAddress < data.Length) + if (resourceTableAddress > initialOffset && resourceTableAddress < data.Length) { // Seek to the resource directory table data.Seek(resourceTableAddress, SeekOrigin.Begin); @@ -170,7 +170,7 @@ namespace SabreTools.Serialization.Deserializers { long certificateTableAddress = initialOffset + optionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (certificateTableAddress != 0 && certificateTableAddress < data.Length) + if (certificateTableAddress > initialOffset && certificateTableAddress < data.Length) { // Seek to the attribute certificate table data.Seek(certificateTableAddress, SeekOrigin.Begin); @@ -190,7 +190,7 @@ namespace SabreTools.Serialization.Deserializers { long baseRelocationTableAddress = initialOffset + optionalHeader.BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (baseRelocationTableAddress != 0 && baseRelocationTableAddress < data.Length) + if (baseRelocationTableAddress > initialOffset && baseRelocationTableAddress < data.Length) { // Seek to the base relocation table data.Seek(baseRelocationTableAddress, SeekOrigin.Begin); @@ -210,7 +210,7 @@ namespace SabreTools.Serialization.Deserializers { long debugTableAddress = initialOffset + optionalHeader.Debug.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (debugTableAddress != 0 && debugTableAddress < data.Length) + if (debugTableAddress > initialOffset && debugTableAddress < data.Length) { // Seek to the debug table data.Seek(debugTableAddress, SeekOrigin.Begin); @@ -236,7 +236,7 @@ namespace SabreTools.Serialization.Deserializers { long delayLoadDirectoryTableAddress = initialOffset + optionalHeader.DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(executable.SectionTable); - if (delayLoadDirectoryTableAddress != 0 && delayLoadDirectoryTableAddress < data.Length) + if (delayLoadDirectoryTableAddress > initialOffset && delayLoadDirectoryTableAddress < data.Length) { // Seek to the delay-load directory table data.Seek(delayLoadDirectoryTableAddress, SeekOrigin.Begin); @@ -664,9 +664,10 @@ namespace SabreTools.Serialization.Deserializers /// Parse a Stream into a ExportTable /// /// Stream to parse + /// Initial offset to use in address comparisons /// Section table to use for virtual address translation /// Filled ExportTable on success, null on error - public static ExportTable ParseExportTable(Stream data, SectionHeader[] sections) + public static ExportTable ParseExportTable(Stream data, long initialOffset, SectionHeader[] sections) { var exportTable = new ExportTable(); @@ -689,7 +690,8 @@ namespace SabreTools.Serialization.Deserializers // Name if (exportDirectoryTable.NameRVA.ConvertVirtualAddress(sections) != 0) { - uint nameAddress = exportDirectoryTable.NameRVA.ConvertVirtualAddress(sections); + long nameAddress = initialOffset + + exportDirectoryTable.NameRVA.ConvertVirtualAddress(sections); data.Seek(nameAddress, SeekOrigin.Begin); string? name = data.ReadNullTerminatedAnsiString(); @@ -699,7 +701,8 @@ namespace SabreTools.Serialization.Deserializers // Address table if (exportDirectoryTable.AddressTableEntries != 0 && exportDirectoryTable.ExportAddressTableRVA.ConvertVirtualAddress(sections) != 0) { - uint exportAddressTableAddress = exportDirectoryTable.ExportAddressTableRVA.ConvertVirtualAddress(sections); + long exportAddressTableAddress = initialOffset + + exportDirectoryTable.ExportAddressTableRVA.ConvertVirtualAddress(sections); data.Seek(exportAddressTableAddress, SeekOrigin.Begin); var exportAddressTable = new ExportAddressTableEntry[exportDirectoryTable.AddressTableEntries]; @@ -715,7 +718,8 @@ namespace SabreTools.Serialization.Deserializers // Name pointer table if (exportDirectoryTable.NumberOfNamePointers != 0 && exportDirectoryTable.NamePointerRVA.ConvertVirtualAddress(sections) != 0) { - uint namePointerTableAddress = exportDirectoryTable.NamePointerRVA.ConvertVirtualAddress(sections); + long namePointerTableAddress = initialOffset + + exportDirectoryTable.NamePointerRVA.ConvertVirtualAddress(sections); data.Seek(namePointerTableAddress, SeekOrigin.Begin); var namePointerTable = new ExportNamePointerTable(); @@ -733,7 +737,8 @@ namespace SabreTools.Serialization.Deserializers // Ordinal table if (exportDirectoryTable.NumberOfNamePointers != 0 && exportDirectoryTable.OrdinalTableRVA.ConvertVirtualAddress(sections) != 0) { - uint ordinalTableAddress = exportDirectoryTable.OrdinalTableRVA.ConvertVirtualAddress(sections); + long ordinalTableAddress = initialOffset + + exportDirectoryTable.OrdinalTableRVA.ConvertVirtualAddress(sections); data.Seek(ordinalTableAddress, SeekOrigin.Begin); var exportOrdinalTable = new ExportOrdinalTable(); @@ -756,7 +761,8 @@ namespace SabreTools.Serialization.Deserializers exportNameTable.Strings = new string[exportDirectoryTable.NumberOfNamePointers]; for (int i = 0; i < exportDirectoryTable.NumberOfNamePointers; i++) { - uint nameAddress = exportTable.NamePointerTable.Pointers[i].ConvertVirtualAddress(sections); ; + long nameAddress = initialOffset + + exportTable.NamePointerTable.Pointers[i].ConvertVirtualAddress(sections); ; data.Seek(nameAddress, SeekOrigin.Begin); string? str = data.ReadNullTerminatedAnsiString(); @@ -806,10 +812,11 @@ namespace SabreTools.Serialization.Deserializers /// Parse a Stream into a import table /// /// Stream to parse + /// Initial offset to use in address comparisons /// Optional header magic number indicating PE32 or PE32+ /// Section table to use for virtual address translation /// Filled import table on success, null on error - public static ImportTable ParseImportTable(Stream data, OptionalHeaderMagicNumber magic, SectionHeader[] sections) + public static ImportTable ParseImportTable(Stream data, long initialOffset, OptionalHeaderMagicNumber magic, SectionHeader[] sections) { var importTable = new ImportTable(); @@ -843,7 +850,8 @@ namespace SabreTools.Serialization.Deserializers if (importDirectoryTableEntry.NameRVA.ConvertVirtualAddress(sections) == 0) continue; - uint nameAddress = importDirectoryTableEntry.NameRVA.ConvertVirtualAddress(sections); + long nameAddress = initialOffset + + importDirectoryTableEntry.NameRVA.ConvertVirtualAddress(sections); data.Seek(nameAddress, SeekOrigin.Begin); string? name = data.ReadNullTerminatedAnsiString(); @@ -862,7 +870,8 @@ namespace SabreTools.Serialization.Deserializers if (importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(sections) == 0) continue; - uint tableAddress = importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(sections); + long tableAddress = initialOffset + + importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(sections); data.Seek(tableAddress, SeekOrigin.Begin); var entryLookupTable = new List(); @@ -916,7 +925,8 @@ namespace SabreTools.Serialization.Deserializers if (importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(sections) == 0) continue; - uint tableAddress = importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(sections); + long tableAddress = initialOffset + + importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(sections); data.Seek(tableAddress, SeekOrigin.Begin); var addressLookupTable = new List(); @@ -1017,7 +1027,8 @@ namespace SabreTools.Serialization.Deserializers hintNameTableEntryAddresses.Sort(); for (int i = 0; i < hintNameTableEntryAddresses.Count; i++) { - int hintNameTableEntryAddress = hintNameTableEntryAddresses[i]; + long hintNameTableEntryAddress = initialOffset + + hintNameTableEntryAddresses[i]; data.Seek(hintNameTableEntryAddress, SeekOrigin.Begin); var hintNameTableEntry = ParseHintNameTableEntry(data); @@ -1199,7 +1210,7 @@ namespace SabreTools.Serialization.Deserializers if (entry.NameOffset > 0) { long currentOffset = data.Position; - offset = entry.NameOffset + (uint)initialOffset; + long nameOffset = initialOffset + entry.NameOffset; data.Seek(offset, SeekOrigin.Begin); var resourceDirectoryString = new ResourceDirectoryString(); @@ -1224,7 +1235,7 @@ namespace SabreTools.Serialization.Deserializers if (entry.DataEntryOffset > 0) { - uint offset = entry.DataEntryOffset + (uint)initialOffset; + long offset = initialOffset + entry.DataEntryOffset; data.Seek(offset, SeekOrigin.Begin); var resourceDataEntry = new ResourceDataEntry(); @@ -1234,7 +1245,7 @@ namespace SabreTools.Serialization.Deserializers resourceDataEntry.Reserved = data.ReadUInt32LittleEndian(); // Read the data from the offset - offset = resourceDataEntry.DataRVA.ConvertVirtualAddress(sections); + offset = initialOffset + resourceDataEntry.DataRVA.ConvertVirtualAddress(sections); if (offset > 0 && resourceDataEntry.Size > 0 && offset + (int)resourceDataEntry.Size < data.Length) { data.Seek(offset, SeekOrigin.Begin); @@ -1245,7 +1256,7 @@ namespace SabreTools.Serialization.Deserializers } else if (entry.SubdirectoryOffset > 0) { - uint offset = entry.SubdirectoryOffset + (uint)initialOffset; + long offset = initialOffset + entry.SubdirectoryOffset; data.Seek(offset, SeekOrigin.Begin); entry.Subdirectory = ParseResourceDirectoryTable(data, initialOffset, sections); diff --git a/SabreTools.Serialization/Deserializers/SGA.cs b/SabreTools.Serialization/Deserializers/SGA.cs index e40a3d4e..626f4607 100644 --- a/SabreTools.Serialization/Deserializers/SGA.cs +++ b/SabreTools.Serialization/Deserializers/SGA.cs @@ -18,6 +18,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new SGA to fill var archive = new Archive(); @@ -158,11 +161,10 @@ namespace SabreTools.Serialization.Deserializers #region Sections // Get and adjust the sections offset - long sectionOffset = directoryHeader.SectionOffset; - sectionOffset += currentOffset; + long sectionOffset = currentOffset + directoryHeader.SectionOffset; // Validate the offset - if (sectionOffset < 0 || sectionOffset >= data.Length) + if (sectionOffset < currentOffset || sectionOffset >= data.Length) return null; // Seek to the sections @@ -182,11 +184,10 @@ namespace SabreTools.Serialization.Deserializers #region Folders // Get and adjust the folders offset - long folderOffset = directoryHeader.FolderOffset; - folderOffset += currentOffset; + long folderOffset = currentOffset + directoryHeader.FolderOffset; // Validate the offset - if (folderOffset < 0 || folderOffset >= data.Length) + if (folderOffset < currentOffset || folderOffset >= data.Length) return null; // Seek to the folders @@ -206,11 +207,10 @@ namespace SabreTools.Serialization.Deserializers #region Files // Get and adjust the files offset - long fileOffset = directoryHeader.FileOffset; - fileOffset += currentOffset; + long fileOffset = currentOffset + directoryHeader.FileOffset; // Validate the offset - if (fileOffset < 0 || fileOffset >= data.Length) + if (fileOffset < currentOffset || fileOffset >= data.Length) return null; // Seek to the files @@ -233,11 +233,10 @@ namespace SabreTools.Serialization.Deserializers #region String Table // Get and adjust the string table offset - long stringTableOffset = directoryHeader.StringTableOffset; - stringTableOffset += currentOffset; + long stringTableOffset = currentOffset + directoryHeader.StringTableOffset; // Validate the offset - if (stringTableOffset < 0 || stringTableOffset >= data.Length) + if (stringTableOffset < currentOffset || stringTableOffset >= data.Length) return null; // Seek to the string table @@ -311,11 +310,10 @@ namespace SabreTools.Serialization.Deserializers #region Sections // Get and adjust the sections offset - long sectionOffset = directoryHeader.SectionOffset; - sectionOffset += currentOffset; + long sectionOffset = currentOffset + directoryHeader.SectionOffset; // Validate the offset - if (sectionOffset < 0 || sectionOffset >= data.Length) + if (sectionOffset < currentOffset || sectionOffset >= data.Length) return null; // Seek to the sections @@ -335,11 +333,10 @@ namespace SabreTools.Serialization.Deserializers #region Folders // Get and adjust the folders offset - long folderOffset = directoryHeader.FolderOffset; - folderOffset += currentOffset; + long folderOffset = currentOffset + directoryHeader.FolderOffset; // Validate the offset - if (folderOffset < 0 || folderOffset >= data.Length) + if (folderOffset < currentOffset || folderOffset >= data.Length) return null; // Seek to the folders @@ -359,11 +356,10 @@ namespace SabreTools.Serialization.Deserializers #region Files // Get and adjust the files offset - long fileOffset = directoryHeader.FileOffset; - fileOffset += currentOffset; + long fileOffset = currentOffset + directoryHeader.FileOffset; // Validate the offset - if (fileOffset < 0 || fileOffset >= data.Length) + if (fileOffset < currentOffset || fileOffset >= data.Length) return null; // Seek to the files @@ -383,11 +379,10 @@ namespace SabreTools.Serialization.Deserializers #region String Table // Get and adjust the string table offset - long stringTableOffset = directoryHeader.StringTableOffset; - stringTableOffset += currentOffset; + long stringTableOffset = currentOffset + directoryHeader.StringTableOffset; // Validate the offset - if (stringTableOffset < 0 || stringTableOffset >= data.Length) + if (stringTableOffset < currentOffset || stringTableOffset >= data.Length) return null; // Seek to the string table @@ -461,11 +456,10 @@ namespace SabreTools.Serialization.Deserializers #region Sections // Get and adjust the sections offset - long sectionOffset = directoryHeader.SectionOffset; - sectionOffset += currentOffset; + long sectionOffset = currentOffset + directoryHeader.SectionOffset; // Validate the offset - if (sectionOffset < 0 || sectionOffset >= data.Length) + if (sectionOffset < currentOffset || sectionOffset >= data.Length) return null; // Seek to the sections @@ -485,11 +479,10 @@ namespace SabreTools.Serialization.Deserializers #region Folders // Get and adjust the folders offset - long folderOffset = directoryHeader.FolderOffset; - folderOffset += currentOffset; + long folderOffset = currentOffset + directoryHeader.FolderOffset; // Validate the offset - if (folderOffset < 0 || folderOffset >= data.Length) + if (folderOffset < currentOffset || folderOffset >= data.Length) return null; // Seek to the folders @@ -509,11 +502,10 @@ namespace SabreTools.Serialization.Deserializers #region Files // Get and adjust the files offset - long fileOffset = directoryHeader.FileOffset; - fileOffset += currentOffset; + long fileOffset = currentOffset + directoryHeader.FileOffset; // Validate the offset - if (fileOffset < 0 || fileOffset >= data.Length) + if (fileOffset < currentOffset || fileOffset >= data.Length) return null; // Seek to the files @@ -533,11 +525,10 @@ namespace SabreTools.Serialization.Deserializers #region String Table // Get and adjust the string table offset - long stringTableOffset = directoryHeader.StringTableOffset; - stringTableOffset += currentOffset; + long stringTableOffset = currentOffset + directoryHeader.StringTableOffset; // Validate the offset - if (stringTableOffset < 0 || stringTableOffset >= data.Length) + if (stringTableOffset < currentOffset || stringTableOffset >= data.Length) return null; // Seek to the string table @@ -611,11 +602,10 @@ namespace SabreTools.Serialization.Deserializers #region Sections // Get and adjust the sections offset - long sectionOffset = directoryHeader.SectionOffset; - sectionOffset += currentOffset; + long sectionOffset = currentOffset + directoryHeader.SectionOffset; // Validate the offset - if (sectionOffset < 0 || sectionOffset >= data.Length) + if (sectionOffset < currentOffset || sectionOffset >= data.Length) return null; // Seek to the sections @@ -635,11 +625,10 @@ namespace SabreTools.Serialization.Deserializers #region Folders // Get and adjust the folders offset - long folderOffset = directoryHeader.FolderOffset; - folderOffset += currentOffset; + long folderOffset = currentOffset + directoryHeader.FolderOffset; // Validate the offset - if (folderOffset < 0 || folderOffset >= data.Length) + if (folderOffset < currentOffset || folderOffset >= data.Length) return null; // Seek to the folders @@ -659,11 +648,10 @@ namespace SabreTools.Serialization.Deserializers #region Files // Get and adjust the files offset - long fileOffset = directoryHeader.FileOffset; - fileOffset += currentOffset; + long fileOffset = currentOffset + directoryHeader.FileOffset; // Validate the offset - if (fileOffset < 0 || fileOffset >= data.Length) + if (fileOffset < currentOffset || fileOffset >= data.Length) return null; // Seek to the files @@ -683,11 +671,10 @@ namespace SabreTools.Serialization.Deserializers #region String Table // Get and adjust the string table offset - long stringTableOffset = directoryHeader.StringTableOffset; - stringTableOffset += currentOffset; + long stringTableOffset = currentOffset + directoryHeader.StringTableOffset; // Validate the offset - if (stringTableOffset < 0 || stringTableOffset >= data.Length) + if (stringTableOffset < currentOffset || stringTableOffset >= data.Length) return null; // Seek to the string table diff --git a/SabreTools.Serialization/Deserializers/VBSP.cs b/SabreTools.Serialization/Deserializers/VBSP.cs index dafe101e..be00dbc7 100644 --- a/SabreTools.Serialization/Deserializers/VBSP.cs +++ b/SabreTools.Serialization/Deserializers/VBSP.cs @@ -20,6 +20,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life 2 Level to fill var file = new VbspFile(); @@ -51,7 +54,7 @@ namespace SabreTools.Serialization.Deserializers continue; // Seek to the lump offset - data.Seek(lumpEntry.Offset, SeekOrigin.Begin); + data.Seek(initialOffset + lumpEntry.Offset, SeekOrigin.Begin); // Read according to the lump type switch ((LumpType)l) diff --git a/SabreTools.Serialization/Deserializers/VPK.cs b/SabreTools.Serialization/Deserializers/VPK.cs index 05d2eecc..0275a230 100644 --- a/SabreTools.Serialization/Deserializers/VPK.cs +++ b/SabreTools.Serialization/Deserializers/VPK.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Valve Package to fill var file = new Models.VPK.File(); @@ -45,7 +48,7 @@ namespace SabreTools.Serialization.Deserializers #region Directory Items // Set the directory items - file.DirectoryItems = ParseDirectoryItemTree(data); + file.DirectoryItems = ParseDirectoryItemTree(data, initialOffset); #endregion @@ -60,10 +63,10 @@ namespace SabreTools.Serialization.Deserializers var archiveHashes = new List(); // Cache the current offset - long initialOffset = data.Position; + long afterHeaderOffset = data.Position; // Try to parse the directory items - while (data.Position < initialOffset + file.ExtendedHeader.ArchiveMD5SectionSize) + while (data.Position < afterHeaderOffset + file.ExtendedHeader.ArchiveMD5SectionSize) { var archiveHash = ParseArchiveHash(data); archiveHashes.Add(archiveHash); @@ -123,8 +126,9 @@ namespace SabreTools.Serialization.Deserializers /// Parse a Stream into a Valve Package directory item /// /// Stream to parse + /// Initial offset to use in address comparisons /// Filled Valve Package directory item on success, null on error - public static DirectoryItem ParseDirectoryItem(Stream data, string extension, string path, string name) + public static DirectoryItem ParseDirectoryItem(Stream data, long initialOffset, string extension, string path, string name) { var obj = new DirectoryItem(); @@ -141,7 +145,7 @@ namespace SabreTools.Serialization.Deserializers && obj.DirectoryEntry.EntryLength > 0 && data.Position + obj.DirectoryEntry.EntryLength <= data.Length) { - preloadDataPointer = obj.DirectoryEntry.EntryOffset; + preloadDataPointer = initialOffset + obj.DirectoryEntry.EntryOffset; preloadDataLength = (int)obj.DirectoryEntry.EntryLength; } else if (obj.DirectoryEntry.PreloadBytes > 0) @@ -152,12 +156,12 @@ namespace SabreTools.Serialization.Deserializers // If we had a valid preload data pointer byte[]? preloadData = null; - if (preloadDataPointer >= 0 + if (preloadDataPointer >= initialOffset && preloadDataLength > 0 && data.Position + preloadDataLength <= data.Length) { // Cache the current offset - long initialOffset = data.Position; + long currentOffset = data.Position; // Seek to the preload data offset data.Seek(preloadDataPointer, SeekOrigin.Begin); @@ -166,7 +170,7 @@ namespace SabreTools.Serialization.Deserializers preloadData = data.ReadBytes(preloadDataLength); // Seek back to the original offset - data.Seek(initialOffset, SeekOrigin.Begin); + data.Seek(currentOffset, SeekOrigin.Begin); } // Set the preload data @@ -179,8 +183,9 @@ namespace SabreTools.Serialization.Deserializers /// Parse a Stream into a Valve Package directory item tree /// /// Stream to parse + /// Initial offset to use in address comparisons /// Filled Valve Package directory item tree on success, null on error - public static DirectoryItem[] ParseDirectoryItemTree(Stream data) + public static DirectoryItem[] ParseDirectoryItemTree(Stream data, long initialOffset) { // Create the directory items list var directoryItems = new List(); @@ -225,7 +230,7 @@ namespace SabreTools.Serialization.Deserializers } // Get the directory item - var directoryItem = ParseDirectoryItem(data, extensionString!, pathString!, nameString!); + var directoryItem = ParseDirectoryItem(data, initialOffset, extensionString!, pathString!, nameString!); // Add the directory item directoryItems.Add(directoryItem); diff --git a/SabreTools.Serialization/Deserializers/WAD3.cs b/SabreTools.Serialization/Deserializers/WAD3.cs index e8b8cc7b..f755bb30 100644 --- a/SabreTools.Serialization/Deserializers/WAD3.cs +++ b/SabreTools.Serialization/Deserializers/WAD3.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new Half-Life Texture Package to fill var file = new Models.WAD3.File(); @@ -35,8 +38,8 @@ namespace SabreTools.Serialization.Deserializers #region Directory Entries // Get the directory offset - uint dirOffset = header.DirOffset; - if (dirOffset < 0 || dirOffset >= data.Length) + long dirOffset = initialOffset + header.DirOffset; + if (dirOffset < initialOffset || dirOffset >= data.Length) return null; // Seek to the lump offset @@ -66,8 +69,8 @@ namespace SabreTools.Serialization.Deserializers continue; // Get the file entry offset - uint fileEntryOffset = dirEntry.Offset; - if (fileEntryOffset < 0 || fileEntryOffset >= data.Length) + long fileEntryOffset = initialOffset + dirEntry.Offset; + if (fileEntryOffset < initialOffset || fileEntryOffset >= data.Length) continue; // Seek to the file entry offset diff --git a/SabreTools.Serialization/Deserializers/XZP.cs b/SabreTools.Serialization/Deserializers/XZP.cs index cb475b8f..a8237634 100644 --- a/SabreTools.Serialization/Deserializers/XZP.cs +++ b/SabreTools.Serialization/Deserializers/XZP.cs @@ -17,6 +17,9 @@ namespace SabreTools.Serialization.Deserializers try { + // Cache the current offset + long initialOffset = data.Position; + // Create a new XBox Package File to fill var file = new Models.XZP.File(); @@ -84,8 +87,8 @@ namespace SabreTools.Serialization.Deserializers if (header.DirectoryItemCount > 0) { // Get the directory item offset - uint directoryItemOffset = header.DirectoryItemOffset; - if (directoryItemOffset < 0 || directoryItemOffset >= data.Length) + long directoryItemOffset = initialOffset + header.DirectoryItemOffset; + if (directoryItemOffset < initialOffset || directoryItemOffset >= data.Length) return null; // Seek to the directory items @@ -97,7 +100,7 @@ namespace SabreTools.Serialization.Deserializers // Try to parse the directory items for (int i = 0; i < file.DirectoryItems.Length; i++) { - file.DirectoryItems[i] = ParseDirectoryItem(data); + file.DirectoryItems[i] = ParseDirectoryItem(data, initialOffset); } } @@ -147,8 +150,9 @@ namespace SabreTools.Serialization.Deserializers /// Parse a Stream into a DirectoryItem /// /// Stream to parse + /// Initial offset to use in address comparisons /// Filled DirectoryItem on success, null on error - public static DirectoryItem ParseDirectoryItem(Stream data) + public static DirectoryItem ParseDirectoryItem(Stream data, long initialOffset) { var obj = new DirectoryItem(); @@ -160,7 +164,7 @@ namespace SabreTools.Serialization.Deserializers long currentPosition = data.Position; // Seek to the name offset - data.Seek(obj.NameOffset, SeekOrigin.Begin); + data.Seek(initialOffset + obj.NameOffset, SeekOrigin.Begin); // Read the name obj.Name = data.ReadNullTerminatedAnsiString();