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
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,14 @@ private ulong GetBytes()
c = this.ReadStream();
}

// Found a marker
// We accept multiple FF bytes followed by a 0 as meaning a single FF data byte.
// This data pattern is not valid according to the standard.
// even though it's considered 'invalid' according to the specs.
if (c != 0)
{
this.Marker = (byte)c;
// It's a trick so we won't read past actual marker
this.badData = true;
this.Marker = (byte)c;
this.MarkerPosition = this.stream.Position - 2;
}
}
Expand Down Expand Up @@ -199,7 +201,6 @@ public bool FindNextMarker()
if (b != 0)
{
this.Marker = (byte)b;
this.badData = true;
this.MarkerPosition = this.stream.Position - 2;
return true;
}
Expand Down
53 changes: 25 additions & 28 deletions src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,38 +164,38 @@ public JpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
/// <summary>
/// Finds the next file marker within the byte stream.
/// </summary>
/// <param name="marker">The buffer to read file markers to.</param>
/// <param name="stream">The input stream.</param>
/// <returns>The <see cref="JpegFileMarker"/></returns>
public static JpegFileMarker FindNextFileMarker(byte[] marker, BufferedReadStream stream)
/// <returns>The <see cref="JpegFileMarker"/>.</returns>
public static JpegFileMarker FindNextFileMarker(BufferedReadStream stream)
{
int value = stream.Read(marker, 0, 2);

if (value == 0)
while (true)
{
return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
}
int b = stream.ReadByte();
if (b == -1)
{
return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
}

if (marker[0] == JpegConstants.Markers.XFF)
{
// According to Section B.1.1.2:
// "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code 0xFF."
int m = marker[1];
while (m == JpegConstants.Markers.XFF)
// Found a marker.
if (b == JpegConstants.Markers.XFF)
{
int suffix = stream.ReadByte();
if (suffix == -1)
while (b == JpegConstants.Markers.XFF)
{
return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
// Loop here to discard any padding FF bytes on terminating marker.
b = stream.ReadByte();
if (b == -1)
{
return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
}
}

m = suffix;
// Found a valid marker. Exit loop
if (b is not 0 and (< JpegConstants.Markers.RST0 or > JpegConstants.Markers.RST7))
{
return new JpegFileMarker((byte)(uint)b, stream.Position - 2);
}
}

return new JpegFileMarker((byte)m, stream.Position - 2);
}

return new JpegFileMarker(marker[1], stream.Position - 2, true);
}

/// <inheritdoc/>
Expand Down Expand Up @@ -331,15 +331,12 @@ internal void ParseStream(BufferedReadStream stream, SpectralConverter spectralC
JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
}

stream.Read(this.markerBuffer, 0, 2);
byte marker = this.markerBuffer[1];
fileMarker = new JpegFileMarker(marker, (int)stream.Position - 2);
fileMarker = FindNextFileMarker(stream);
this.QuantizationTables ??= new Block8x8F[4];

// Break only when we discover a valid EOI marker.
// https://github.com/SixLabors/ImageSharp/issues/695
while (fileMarker.Marker != JpegConstants.Markers.EOI
|| (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid))
while (fileMarker.Marker != JpegConstants.Markers.EOI)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -491,7 +488,7 @@ internal void ParseStream(BufferedReadStream stream, SpectralConverter spectralC
}

// Read on.
fileMarker = FindNextFileMarker(this.markerBuffer, stream);
fileMarker = FindNextFileMarker(stream);
}
}

Expand Down
15 changes: 14 additions & 1 deletion tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public void Issue2057_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)

// https://github.com/SixLabors/ImageSharp/issues/2133
[Theory]
[WithFile(TestImages.Jpeg.Issues.Issue2133DeduceColorSpace, PixelTypes.Rgba32)]
[WithFile(TestImages.Jpeg.Issues.Issue2133_DeduceColorSpace, PixelTypes.Rgba32)]
public void Issue2133_DeduceColorSpace<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Expand All @@ -231,6 +231,19 @@ public void Issue2133_DeduceColorSpace<TPixel>(TestImageProvider<TPixel> provide
}
}

// https://github.com/SixLabors/ImageSharp/issues/2133
[Theory]
[WithFile(TestImages.Jpeg.Issues.Issue2136_ScanMarkerExtraneousBytes, PixelTypes.Rgba32)]
public void Issue2136_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
}

// DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\"
Expand Down
3 changes: 2 additions & 1 deletion tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ public static class Issues
public const string Issue2057App1Parsing = "Jpg/issues/Issue2057-App1Parsing.jpg";
public const string ExifNullArrayTag = "Jpg/issues/issue-2056-exif-null-array.jpg";
public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg";
public const string Issue2133DeduceColorSpace = "Jpg/issues/Issue2133.jpg";
public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg";
public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg";

public static class Fuzz
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.