Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/ImageSharp/Formats/Gif/GifDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
/// </summary>
private void ReadGraphicalControlExtension()
{
this.stream.Read(this.buffer, 0, 6);
int bytesRead = this.stream.Read(this.buffer, 0, 6);
if (bytesRead != 6)
{
GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the graphic control extension");
}

this.graphicsControlExtension = GifGraphicControlExtension.Parse(this.buffer);
}
Expand All @@ -231,7 +235,11 @@ private void ReadGraphicalControlExtension()
/// </summary>
private void ReadImageDescriptor()
{
this.stream.Read(this.buffer, 0, 9);
int bytesRead = this.stream.Read(this.buffer, 0, 9);
if (bytesRead != 9)
{
GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the image descriptor");
}

this.imageDescriptor = GifImageDescriptor.Parse(this.buffer);
if (this.imageDescriptor.Height == 0 || this.imageDescriptor.Width == 0)
Expand All @@ -245,7 +253,11 @@ private void ReadImageDescriptor()
/// </summary>
private void ReadLogicalScreenDescriptor()
{
this.stream.Read(this.buffer, 0, 7);
int bytesRead = this.stream.Read(this.buffer, 0, 7);
if (bytesRead != 7)
{
GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the logical screen descriptor");
}

this.logicalScreenDescriptor = GifLogicalScreenDescriptor.Parse(this.buffer);
}
Expand Down
60 changes: 47 additions & 13 deletions src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,28 +228,41 @@ public void LoadTables(byte[] tableBytes, HuffmanScanDecoder huffmanScanDecoder)
this.Metadata = new ImageMetadata();
this.QuantizationTables = new Block8x8F[4];
this.scanDecoder = huffmanScanDecoder;

if (tableBytes.Length < 4)
{
JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read marker");
}

using var ms = new MemoryStream(tableBytes);
using var stream = new BufferedReadStream(this.Configuration, ms);

// Check for the Start Of Image marker.
stream.Read(this.markerBuffer, 0, 2);
int bytesRead = stream.Read(this.markerBuffer, 0, 2);
var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
if (fileMarker.Marker != JpegConstants.Markers.SOI)
{
JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
}

// Read next marker.
stream.Read(this.markerBuffer, 0, 2);
byte marker = this.markerBuffer[1];
fileMarker = new JpegFileMarker(marker, (int)stream.Position - 2);
bytesRead = stream.Read(this.markerBuffer, 0, 2);
fileMarker = new JpegFileMarker(this.markerBuffer[1], (int)stream.Position - 2);

while (fileMarker.Marker != JpegConstants.Markers.EOI || (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid))
{
if (!fileMarker.Invalid)
{
// Get the marker length.
int remaining = this.ReadUint16(stream) - 2;
int markerContentByteSize = this.ReadUint16(stream) - 2;

// Check whether stream actually has enought bytes to read
// markerContentByteSize is always positive so we cast
// to uint to avoid sign extension
if (stream.RemainingBytes < (uint)markerContentByteSize)
{
JpegThrowHelper.ThrowNotEnoughBytesForMarker(fileMarker.Marker);
}

switch (fileMarker.Marker)
{
Expand All @@ -259,21 +272,26 @@ public void LoadTables(byte[] tableBytes, HuffmanScanDecoder huffmanScanDecoder)
case JpegConstants.Markers.RST7:
break;
case JpegConstants.Markers.DHT:
this.ProcessDefineHuffmanTablesMarker(stream, remaining);
this.ProcessDefineHuffmanTablesMarker(stream, markerContentByteSize);
break;
case JpegConstants.Markers.DQT:
this.ProcessDefineQuantizationTablesMarker(stream, remaining);
this.ProcessDefineQuantizationTablesMarker(stream, markerContentByteSize);
break;
case JpegConstants.Markers.DRI:
this.ProcessDefineRestartIntervalMarker(stream, remaining);
this.ProcessDefineRestartIntervalMarker(stream, markerContentByteSize);
break;
case JpegConstants.Markers.EOI:
return;
}
}

// Read next marker.
stream.Read(this.markerBuffer, 0, 2);
bytesRead = stream.Read(this.markerBuffer, 0, 2);
if (bytesRead != 2)
{
JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read marker");
}

fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
}
}
Expand Down Expand Up @@ -730,7 +748,14 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)

if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(0, ExifMarkerLength)))
{
int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength;
const int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength;
if (remaining < remainingXmpMarkerBytes || this.IgnoreMetadata)
{
// Skip the application header length.
stream.Skip(remaining);
return;
}

stream.Read(this.temp, ExifMarkerLength, remainingXmpMarkerBytes);
remaining -= remainingXmpMarkerBytes;
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker))
Expand Down Expand Up @@ -1320,8 +1345,12 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining)
component.ACHuffmanTableId = acTableIndex;
}

// 3 bytes: Progressive scan decoding data
stream.Read(this.temp, 0, 3);
// 3 bytes: Progressive scan decoding data.
int bytesRead = stream.Read(this.temp, 0, 3);
if (bytesRead != 3)
{
JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read progressive scan decoding data");
}

int spectralStart = this.temp[0];
this.scanDecoder.SpectralStart = spectralStart;
Expand All @@ -1344,7 +1373,12 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining)
[MethodImpl(InliningOptions.ShortMethod)]
private ushort ReadUint16(BufferedReadStream stream)
{
stream.Read(this.markerBuffer, 0, 2);
int bytesRead = stream.Read(this.markerBuffer, 0, 2);
if (bytesRead != 2)
{
JpegThrowHelper.ThrowInvalidImageContentException("jpeg stream does not contain enough data, could not read ushort.");
}

return BinaryPrimitives.ReadUInt16BigEndian(this.markerBuffer);
}
}
Expand Down
Loading