In ISO9660 filesystem pass thru error reading extents. Fixes #652

This commit is contained in:
2022-05-21 18:52:42 +01:00
parent c488411b75
commit 82f2fd6396
4 changed files with 89 additions and 63 deletions

View File

@@ -164,7 +164,10 @@ public sealed partial class ISO9660
Dictionary<string, DecodedDirectoryEntry> entries = new();
var entryOff = 0;
byte[] data = ReadSingleExtent(size, (uint)start);
ErrorNumber errno = ReadSingleExtent(size, (uint)start, out byte[] data);
if(errno != ErrorNumber.NoError)
return entries;
while(entryOff + _cdiDirectoryRecordSize < data.Length)
{
@@ -241,7 +244,10 @@ public sealed partial class ISO9660
Dictionary<string, DecodedDirectoryEntry> entries = new();
var entryOff = 0;
byte[] data = ReadSingleExtent(size, (uint)start);
ErrorNumber errno = ReadSingleExtent(size, (uint)start, out byte[] data);
if(errno != ErrorNumber.NoError)
return entries;
while(entryOff + _directoryRecordSize < data.Length)
{
@@ -312,7 +318,10 @@ public sealed partial class ISO9660
Dictionary<string, DecodedDirectoryEntry> entries = new();
var entryOff = 0;
byte[] data = ReadSingleExtent(size, (uint)start);
ErrorNumber errno = ReadSingleExtent(size, (uint)start, out byte[] data);
if(errno != ErrorNumber.NoError)
return entries;
while(entryOff + _directoryRecordSize < data.Length)
{
@@ -477,10 +486,13 @@ public sealed partial class ISO9660
if(transTblEntry.Value == null)
return;
byte[] transTbl = ReadWithExtents(0, (long)transTblEntry.Value.Size, transTblEntry.Value.Extents,
transTblEntry.Value.XA?.signature == XA_MAGIC &&
transTblEntry.Value.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
transTblEntry.Value.XA?.filenumber ?? 0);
ErrorNumber errno = ReadWithExtents(0, (long)transTblEntry.Value.Size, transTblEntry.Value.Extents,
transTblEntry.Value.XA?.signature == XA_MAGIC &&
transTblEntry.Value.XA?.attributes.HasFlag(XaAttributes.Interleaved) ==
true, transTblEntry.Value.XA?.filenumber ?? 0, out byte[] transTbl);
if(errno != ErrorNumber.NoError)
return;
var mr = new MemoryStream(transTbl, 0, (int)transTblEntry.Value.Size, false);
var sr = new StreamReader(mr, Encoding);
@@ -957,9 +969,10 @@ public sealed partial class ISO9660
Marshal.ByteArrayToStructureLittleEndian<ContinuationArea>(data, systemAreaOff,
Marshal.SizeOf<ContinuationArea>());
byte[] caData = ReadSingleExtent(ca.offset, ca.ca_length, ca.block);
errno = ReadSingleExtent(ca.offset, ca.ca_length, ca.block, out byte[] caData);
DecodeSystemArea(caData, 0, (int)ca.ca_length, ref entry, out hasResourceFork);
if(errno == ErrorNumber.NoError)
DecodeSystemArea(caData, 0, (int)ca.ca_length, ref entry, out hasResourceFork);
systemAreaOff += ceLength;

View File

@@ -157,12 +157,10 @@ public sealed partial class ISO9660
return ErrorNumber.UnexpectedException;
}
buf = ReadWithExtents(offset, size, entry.Extents,
entry.XA?.signature == XA_MAGIC &&
entry.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.XA?.filenumber ?? 0);
return ErrorNumber.NoError;
return ReadWithExtents(offset, size, entry.Extents,
entry.XA?.signature == XA_MAGIC &&
entry.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.XA?.filenumber ?? 0, out buf);
}
/// <inheritdoc />
@@ -384,7 +382,10 @@ public sealed partial class ISO9660
stat.Mode |= 256;
}
byte[] ea = ReadSingleExtent(entry.XattrLength * _blockSize, entry.Extents[0].extent);
ErrorNumber errno = ReadSingleExtent(entry.XattrLength * _blockSize, entry.Extents[0].extent, out byte[] ea);
if(errno != ErrorNumber.NoError)
return ErrorNumber.NoError;
ExtendedAttributeRecord ear = Marshal.ByteArrayToStructureLittleEndian<ExtendedAttributeRecord>(ea);
@@ -491,22 +492,23 @@ public sealed partial class ISO9660
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
byte[] ReadSingleExtent(long size, uint startingSector, bool interleaved = false, byte fileNumber = 0) =>
ReadWithExtents(0, size, new List<(uint extent, uint size)>
{
(startingSector, (uint)size)
}, interleaved, fileNumber);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
byte[] ReadSingleExtent(long offset, long size, uint startingSector, bool interleaved = false,
byte fileNumber = 0) => ReadWithExtents(offset, size, new List<(uint extent, uint size)>
ErrorNumber ReadSingleExtent(long size, uint startingSector, out byte[] buffer, bool interleaved = false,
byte fileNumber = 0) => ReadWithExtents(0, size, new List<(uint extent, uint size)>
{
(startingSector, (uint)size)
}, interleaved, fileNumber);
}, interleaved, fileNumber, out buffer);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
ErrorNumber ReadSingleExtent(long offset, long size, uint startingSector, out byte[] buffer,
bool interleaved = false, byte fileNumber = 0) => ReadWithExtents(offset, size,
new List<(uint extent, uint size)>
{
(startingSector, (uint)size)
}, interleaved, fileNumber, out buffer);
// Cannot think how to make this faster, as we don't know the mode sector until it is read, but we have size in bytes
byte[] ReadWithExtents(long offset, long size, List<(uint extent, uint size)> extents, bool interleaved,
byte fileNumber)
ErrorNumber ReadWithExtents(long offset, long size, List<(uint extent, uint size)> extents, bool interleaved,
byte fileNumber, out byte[] buffer)
{
var ms = new MemoryStream();
long currentFilePos = 0;
@@ -528,10 +530,18 @@ public sealed partial class ISO9660
ErrorNumber errno = ReadSector(extents[i].extent + currentExtentSector, out byte[] sector, interleaved,
fileNumber);
if(errno != ErrorNumber.NoError ||
sector is null)
if(errno != ErrorNumber.NoError)
{
buffer = ms.ToArray();
return errno;
}
if(sector is null)
{
currentExtentSector++;
leftExtentSize -= 2048;
currentFilePos += 2048;
continue;
}
@@ -565,7 +575,9 @@ public sealed partial class ISO9660
if(ms.Length >= size)
ms.SetLength(size);
return ms.ToArray();
buffer = ms.ToArray();
return ErrorNumber.NoError;
}
byte[] ReadSubheaderWithExtents(List<(uint extent, uint size)> extents, bool copy)

View File

@@ -288,8 +288,11 @@ public sealed partial class ISO9660
{
_blockSize = hsvd.Value.logical_block_size;
pathTableData = ReadSingleExtent(hsvd.Value.path_table_size,
Swapping.Swap(hsvd.Value.mandatory_path_table_msb));
errno = ReadSingleExtent(hsvd.Value.path_table_size, Swapping.Swap(hsvd.Value.mandatory_path_table_msb),
out pathTableData);
if(errno != ErrorNumber.NoError)
pathTableData = null;
fsFormat = "High Sierra Format";
@@ -300,7 +303,10 @@ public sealed partial class ISO9660
{
_blockSize = fsvd.Value.logical_block_size;
pathTableData = ReadSingleExtent(fsvd.Value.path_table_size, fsvd.Value.path_table_addr);
errno = ReadSingleExtent(fsvd.Value.path_table_size, fsvd.Value.path_table_addr, out pathTableData);
if(errno != ErrorNumber.NoError)
pathTableData = null;
fsFormat = "CD-i";
@@ -313,7 +319,11 @@ public sealed partial class ISO9660
{
_blockSize = pvd.Value.logical_block_size;
pathTableData = ReadSingleExtent(pvd.Value.path_table_size, Swapping.Swap(pvd.Value.type_m_path_table));
errno = ReadSingleExtent(pvd.Value.path_table_size, Swapping.Swap(pvd.Value.type_m_path_table),
out pathTableData);
if(errno != ErrorNumber.NoError)
pathTableData = null;
fsFormat = "ISO9660";
@@ -325,7 +335,7 @@ public sealed partial class ISO9660
if(_pathTable is null)
{
pathTableData = ReadSingleExtent(pathTableData.Length, pathTableLsbLocation);
ReadSingleExtent(pathTableData.Length, pathTableLsbLocation, out pathTableData);
_pathTable = _highSierra ? DecodeHighSierraPathTable(pathTableData) : DecodePathTable(pathTableData);
}
@@ -472,7 +482,7 @@ public sealed partial class ISO9660
try
{
_ = ReadSingleExtent(rootSize, rootLocation);
ReadSingleExtent(rootSize, rootLocation, out byte[] _);
}
catch
{
@@ -748,12 +758,10 @@ public sealed partial class ISO9660
_statfs = new FileSystemInfo
{
Blocks = decodedVd.Blocks,
FilenameLength = (ushort)(jolietvd != null ? _namespace == Namespace.Joliet
? 110
: 255 : 255),
PluginId = Id,
Type = fsFormat
Blocks = decodedVd.Blocks,
FilenameLength = (ushort)(jolietvd != null ? _namespace == Namespace.Joliet ? 110 : 255 : 255),
PluginId = Id,
Type = fsFormat
};
_directoryCache = new Dictionary<string, Dictionary<string, DecodedDirectoryEntry>>();

View File

@@ -114,15 +114,12 @@ public sealed partial class ISO9660
switch(xattr)
{
case "org.iso.9660.ea":
if(entry.XattrLength == 0)
return ErrorNumber.NoSuchExtendedAttribute;
return entry.XattrLength == 0
? ErrorNumber.NoSuchExtendedAttribute
: entry.Extents is null
? ErrorNumber.InvalidArgument
: ReadSingleExtent(entry.XattrLength * _blockSize, entry.Extents[0].extent, out buf);
if(entry.Extents is null)
return ErrorNumber.InvalidArgument;
buf = ReadSingleExtent(entry.XattrLength * _blockSize, entry.Extents[0].extent);
return ErrorNumber.NoError;
case "org.iso.9660.AssociatedFile":
if(entry.AssociatedFile is null)
return ErrorNumber.NoSuchExtendedAttribute;
@@ -137,12 +134,10 @@ public sealed partial class ISO9660
return ErrorNumber.NoError;
}
buf = ReadWithExtents(0, (long)entry.AssociatedFile.Size, entry.AssociatedFile.Extents,
entry.AssociatedFile.XA?.signature == XA_MAGIC &&
entry.AssociatedFile.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.AssociatedFile.XA?.filenumber ?? 0);
return ErrorNumber.NoError;
return ReadWithExtents(0, (long)entry.AssociatedFile.Size, entry.AssociatedFile.Extents,
entry.AssociatedFile.XA?.signature == XA_MAGIC &&
entry.AssociatedFile.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.AssociatedFile.XA?.filenumber ?? 0, out buf);
case "com.apple.dos.type":
if(entry.AppleDosType is null)
return ErrorNumber.NoSuchExtendedAttribute;
@@ -172,12 +167,10 @@ public sealed partial class ISO9660
return ErrorNumber.NoError;
}
buf = ReadWithExtents(0, (long)entry.ResourceFork.Size, entry.ResourceFork.Extents,
entry.ResourceFork.XA?.signature == XA_MAGIC &&
entry.ResourceFork.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.ResourceFork.XA?.filenumber ?? 0);
return ErrorNumber.NoError;
return ReadWithExtents(0, (long)entry.ResourceFork.Size, entry.ResourceFork.Extents,
entry.ResourceFork.XA?.signature == XA_MAGIC &&
entry.ResourceFork.XA?.attributes.HasFlag(XaAttributes.Interleaved) == true,
entry.ResourceFork.XA?.filenumber ?? 0, out buf);
case "com.apple.FinderInfo":
if(entry.FinderInfo is null)
return ErrorNumber.NoSuchExtendedAttribute;