Browse Source

Allow zero DPI and only throw at EOF when not enough data

pull/2324/head
James Jackson-South 3 years ago
parent
commit
3c2885e382
  1. 22
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
  3. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  4. 12
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  5. 11
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  6. 2
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  7. 1
      tests/ImageSharp.Tests/TestImages.cs
  8. 3
      tests/Images/Input/Jpg/issues/issue-2315.jpg

22
src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs

@ -26,16 +26,6 @@ internal readonly struct JFifMarker : IEquatable<JFifMarker>
/// <param name="yDensity">The vertical pixel density.</param>
private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity)
{
if (xDensity <= 0)
{
JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0.");
}
if (yDensity <= 0)
{
JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0.");
}
this.MajorVersion = majorVersion;
this.MinorVersion = minorVersion;
@ -64,12 +54,12 @@ internal readonly struct JFifMarker : IEquatable<JFifMarker>
public PixelResolutionUnit DensityUnits { get; }
/// <summary>
/// Gets the horizontal pixel density. Must not be zero.
/// Gets the horizontal pixel density.
/// </summary>
public short XDensity { get; }
/// <summary>
/// Gets the vertical pixel density. Must not be zero.
/// Gets the vertical pixel density.
/// </summary>
public short YDensity { get; }
@ -88,12 +78,8 @@ internal readonly struct JFifMarker : IEquatable<JFifMarker>
byte densityUnits = bytes[7];
short xDensity = (short)((bytes[8] << 8) | bytes[9]);
short yDensity = (short)((bytes[10] << 8) | bytes[11]);
if (xDensity > 0 && yDensity > 0)
{
marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity);
return true;
}
marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity);
return true;
}
marker = default;

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs

@ -121,4 +121,10 @@ internal abstract class SpectralConverter
return size;
}
/// <summary>
/// Gets a value indicating whether the converter has a pixel buffer.
/// </summary>
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
public abstract bool HasPixelBuffer();
}

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -85,6 +85,12 @@ internal class SpectralConverter<TPixel> : SpectralConverter, IDisposable
/// </summary>
public Configuration Configuration { get; }
/// <summary>
/// Gets a value indicating whether the converter has a pixel buffer.
/// </summary>
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
public override bool HasPixelBuffer() => this.pixelBuffer is not null;
/// <summary>
/// Gets converted pixel buffer.
/// </summary>

12
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -356,6 +356,18 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals
// to uint to avoid sign extension.
if (stream.RemainingBytes < (uint)markerContentByteSize)
{
if (metadataOnly && this.Metadata != null && this.Frame != null)
{
// We have enough data to decode the image, so we can stop parsing.
return;
}
if (this.Metadata != null && this.Frame != null && spectralConverter.HasPixelBuffer())
{
// We have enough data to decode the image, so we can stop parsing.
return;
}
JpegThrowHelper.ThrowNotEnoughBytesForMarker(fileMarker.Marker);
}

11
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -300,4 +300,15 @@ public partial class JpegDecoderTests
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
// https://github.com/SixLabors/ImageSharp/issues/2315
[Theory]
[WithFile(TestImages.Jpeg.Issues.Issue2315_NotEnoughBytes, PixelTypes.Rgba32)]
public void Issue2315_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
}

2
tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

@ -187,6 +187,8 @@ public class SpectralJpegTests
}
}
public override bool HasPixelBuffer() => throw new NotImplementedException();
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)
{
this.frame = frame;

1
tests/ImageSharp.Tests/TestImages.cs

@ -281,6 +281,7 @@ public static class TestImages
public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg";
public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg";
public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg";
public const string Issue2315_NotEnoughBytes = "Jpg/issues/issue-2315.jpg";
public static class Fuzz
{

3
tests/Images/Input/Jpg/issues/issue-2315.jpg

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f129b057efb499d492e9afcffdd98de62aac1e04b97a09a75b4799ba498cd3c1
size 319056
Loading…
Cancel
Save