Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
45 changes: 38 additions & 7 deletions src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,25 @@ public void LoadTables(byte[] tableBytes, HuffmanScanDecoder huffmanScanDecoder)
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);
if (bytesRead != 2)
{
JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read the SOI marker");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this and similar checks from other marker parsing methods as it's now guaranteed that stream has at least remaining bytes available.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... That method is actually called from TIFF only.

Copy link
Contributor

@br3aker br3aker Apr 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we still can transform 2 read checks to 1 AvailableBytes check :)
I can't comment on non diff lines but that method creates stream:

using var ms = new MemoryStream(tableBytes);

and then do 2 reads of 2 bytes with sequential if checks.

We can do this check:

if(tableBytes.Length < 4)  throw ...

before even creating a stream and remove 2 checks after reads as those would always be true.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Will have a look.


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);
bytesRead = stream.Read(this.markerBuffer, 0, 2);
if (bytesRead != 2)
{
JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read marker");
}

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

Expand Down Expand Up @@ -273,7 +283,12 @@ public void LoadTables(byte[] tableBytes, HuffmanScanDecoder huffmanScanDecoder)
}

// 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 +745,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 +1342,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 +1370,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