From 919014a109d96f3f8da702cd1f31d083d314e393 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Sat, 12 Apr 2025 11:40:22 +0200 Subject: [PATCH] Detect end of stream better --- MatFileHandler/DataElementReader.cs | 50 ++++++++++++++++++++++------- MatFileHandler/MatFileReader.cs | 32 +++++++++--------- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/MatFileHandler/DataElementReader.cs b/MatFileHandler/DataElementReader.cs index 8a4ae9c..b05406e 100755 --- a/MatFileHandler/DataElementReader.cs +++ b/MatFileHandler/DataElementReader.cs @@ -30,9 +30,15 @@ namespace MatFileHandler /// /// Input reader. /// Data element. - public DataElement Read(BinaryReader reader) + public DataElement? Read(BinaryReader reader) { - var (dataReader, tag) = ReadTag(reader); + var maybeTagPair = ReadTag(reader); + if (maybeTagPair is not { } tagPair) + { + return null; + } + + var (dataReader, tag) = tagPair; var result = tag.Type switch { @@ -167,9 +173,31 @@ namespace MatFileHandler }; } - private static (BinaryReader reader, Tag tag) ReadTag(BinaryReader reader) + private static int? TryReadInt32(BinaryReader reader) { - var type = reader.ReadInt32(); + var buffer = new byte[4]; + var position = 0; + while (position < 4) + { + var actually = reader.BaseStream.Read(buffer, position, 4 - position); + if (actually == 0) + { + return null; + } + position += actually; + } + + return BitConverter.ToInt32(buffer, 0); + } + + private static (BinaryReader reader, Tag tag)? ReadTag(BinaryReader reader) + { + var maybeType = TryReadInt32(reader); + if (maybeType is not int type) + { + return null; + } + var typeHi = type >> 16; if (typeHi == 0) { @@ -214,7 +242,7 @@ namespace MatFileHandler var classNameElement = Read(reader) as MiNum ?? throw new HandlerException("Unexpected type in class name."); var className = ReadName(classNameElement); - var dataElement = Read(reader); + var dataElement = Read(reader) ?? throw new HandlerException("Missing opaque data element."); var data = ReadData(dataElement); if (data is MatNumericalArrayOf linkElement) { @@ -246,7 +274,7 @@ namespace MatFileHandler throw new HandlerException("Unexpected type in row indices of a sparse array."); var columnIndex = Read(reader) as MiNum ?? throw new HandlerException("Unexpected type in column indices of a sparse array."); - var data = Read(reader); + var data = Read(reader) ?? throw new HandlerException("Missing sparse array data."); if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsLogical)) { return DataElementConverter.ConvertToMatSparseArrayOf( @@ -260,7 +288,7 @@ namespace MatFileHandler if (sparseArrayFlags.ArrayFlags.Variable.HasFlag(Variable.IsComplex)) { - var imaginaryData = Read(reader); + var imaginaryData = Read(reader) ?? throw new HandlerException("Missing imaginary part of sparse array data."); return DataElementConverter.ConvertToMatSparseArrayOfComplex( sparseArrayFlags, dimensions, @@ -327,7 +355,7 @@ namespace MatFileHandler using (var positionTrackingStream = new PositionTrackingStream(bufferedStream)) using (var innerReader = new BinaryReader(positionTrackingStream)) { - element = Read(innerReader); + element = Read(innerReader) ?? throw new HandlerException("Missing compressed data."); } if (substream.Position != substream.Length) @@ -350,7 +378,7 @@ namespace MatFileHandler return MatArray.Empty(); } - var element1 = Read(reader); + var element1 = Read(reader) ?? throw new HandlerException("Missing matrix data."); var flags = ReadArrayFlags(element1); if (flags.Class == ArrayType.MxOpaque) { @@ -372,12 +400,12 @@ namespace MatFileHandler return ContinueReadingSparseArray(reader, element1, dimensions, name); } - var element4 = Read(reader); + var element4 = Read(reader) ?? throw new HandlerException("Missing matrix data."); var data = ReadData(element4); DataElement? imaginaryData = null; if (flags.Variable.HasFlag(Variable.IsComplex)) { - var element5 = Read(reader); + var element5 = Read(reader) ?? throw new HandlerException("Missing complex matrix data."); imaginaryData = ReadData(element5); } diff --git a/MatFileHandler/MatFileReader.cs b/MatFileHandler/MatFileReader.cs index af48d17..6c9e5d5 100755 --- a/MatFileHandler/MatFileReader.cs +++ b/MatFileHandler/MatFileReader.cs @@ -48,26 +48,24 @@ namespace MatFileHandler var dataElementReader = new DataElementReader(subsystemData); while (true) { - try - { - var position = reader.BaseStream.Position; - var dataElement = dataElementReader.Read(reader); - if (position == subsystemDataOffset) - { - var subsystemDataElement = dataElement as IArrayOf - ?? throw new HandlerException("Cannot parse subsystem data element."); - var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData); - subsystemData.Set(newSubsystemData); - } - else - { - variables.Add(new RawVariable(position, dataElement)); - } - } - catch (EndOfStreamException) + var position = reader.BaseStream.Position; + var dataElement = dataElementReader.Read(reader); + if (dataElement is null) { break; } + + if (position == subsystemDataOffset) + { + var subsystemDataElement = dataElement as IArrayOf + ?? throw new HandlerException("Cannot parse subsystem data element."); + var newSubsystemData = ReadSubsystemData(subsystemDataElement.Data, subsystemData); + subsystemData.Set(newSubsystemData); + } + else + { + variables.Add(new RawVariable(position, dataElement)); + } } return variables;