Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
903e4cd
Nomalize jpeg exceptions. Fix #821
JimBobSquarePants Feb 15, 2019
7fa95ec
Merge branch 'master' into js/jpeg-security
JimBobSquarePants Feb 15, 2019
9823c85
Merge branch 'master' into js/jpeg-security
JimBobSquarePants Feb 15, 2019
925b25d
Fix #822
JimBobSquarePants Feb 15, 2019
fdeb6ea
Fix #823
JimBobSquarePants Feb 16, 2019
9722e81
Check for correct QT index. Touch #824
JimBobSquarePants Feb 16, 2019
af78ccf
Check DHT props. Touch #824
JimBobSquarePants Feb 16, 2019
bf55db7
Limit sampling factors to 1 & 2. Touch #824
JimBobSquarePants Feb 16, 2019
e984f86
Add already fixed image 4. Touch #824
JimBobSquarePants Feb 16, 2019
510c363
Check for excessive code lengths. Touch #824
JimBobSquarePants Feb 16, 2019
9efdcb6
Add already fixed image 6. Touch #824
JimBobSquarePants Feb 16, 2019
8d974c5
Lint progressive scan details. Touch #824
JimBobSquarePants Feb 16, 2019
c405175
Add already fixed image 8. Fix #824
JimBobSquarePants Feb 16, 2019
e4b2cb7
Remove duplicate per-block checks
JimBobSquarePants Feb 16, 2019
6cb10dc
Add already fixed image 1. Touch #825
JimBobSquarePants Feb 16, 2019
d6703d8
Don't throw on bad JFIF density units.
JimBobSquarePants Feb 17, 2019
9bbd69a
Add already fixed image 3. Touch #825
JimBobSquarePants Feb 17, 2019
23b7161
Add already fixed image 4. Fix #825
JimBobSquarePants Feb 17, 2019
e340769
Check SOFn marker length. Touch #826
JimBobSquarePants Feb 17, 2019
cf98f53
Add already fixed image 2. Touch #826
JimBobSquarePants Feb 17, 2019
6f83609
Add already fixed image 3. Fix #826
JimBobSquarePants Feb 17, 2019
caacfc3
Add fixed already fixed image. Fix #827
JimBobSquarePants Feb 17, 2019
1e38243
Revert unneeded bounds check introduced in #804
JimBobSquarePants Feb 17, 2019
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
Next Next commit
Nomalize jpeg exceptions. Fix #821
  • Loading branch information
JimBobSquarePants committed Feb 15, 2019
commit 903e4cd63755975dd2f9bb478f5fbadf477e4df3
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
Expand All @@ -23,6 +21,12 @@ public JpegComponent(MemoryAllocator memoryAllocator, JpegFrame frame, byte id,
this.memoryAllocator = memoryAllocator;
this.Frame = frame;
this.Id = id;

if (horizontalFactor == 0 || verticalFactor == 0)
{
JpegThrowHelper.ThrowImageFormatException("Bad Sampling factor.");
}

this.HorizontalSamplingFactor = horizontalFactor;
this.VerticalSamplingFactor = verticalFactor;
this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void Dispose()
{
for (int i = 0; i < this.Components.Length; i++)
{
this.Components[i].Dispose();
this.Components[i]?.Dispose();
}

this.Components = null;
Expand Down
4 changes: 2 additions & 2 deletions src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ private void DecodeBlockProgressiveDC(
{
if (this.spectralEnd != 0)
{
JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC.");
JpegThrowHelper.ThrowNoMergeDcAc();
}

this.CheckBits();
Expand Down Expand Up @@ -520,7 +520,7 @@ private void DecodeBlockProgressiveAC(
{
if (this.spectralStart == 0)
{
JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC.");
JpegThrowHelper.ThrowNoMergeDcAc();
}

ref short blockDataRef = ref Unsafe.As<Block8x8, short>(ref block);
Expand Down
30 changes: 21 additions & 9 deletions src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void ParseStream(Stream stream, bool metadataOnly = false)
var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
if (fileMarker.Marker != JpegConstants.Markers.SOI)
{
throw new ImageFormatException("Missing SOI marker.");
JpegThrowHelper.ThrowImageFormatException("Missing SOI marker.");
}

this.InputStream.Read(this.markerBuffer, 0, 2);
Expand Down Expand Up @@ -419,7 +419,8 @@ private JpegColorSpace DeduceJpegColorSpace()
: JpegColorSpace.Cmyk;
}

throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}");
JpegThrowHelper.ThrowImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}");
return default;
}

/// <summary>
Expand Down Expand Up @@ -690,7 +691,8 @@ private void ProcessDefineQuantizationTablesMarker(int remaining)

break;
default:
throw new ImageFormatException("Bad Tq index value");
JpegThrowHelper.ThrowImageFormatException("Bad Tq index value");
break;
}

if (done)
Expand All @@ -701,7 +703,7 @@ private void ProcessDefineQuantizationTablesMarker(int remaining)

if (remaining != 0)
{
throw new ImageFormatException("DQT has wrong length");
JpegThrowHelper.ThrowImageFormatException("DQT has wrong length");
}

this.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables);
Expand All @@ -717,15 +719,15 @@ private void ProcessStartOfFrameMarker(int remaining, in JpegFileMarker frameMar
{
if (this.Frame != null)
{
throw new ImageFormatException("Multiple SOF markers. Only single frame jpegs supported.");
JpegThrowHelper.ThrowImageFormatException("Multiple SOF markers. Only single frame jpegs supported.");
}

this.InputStream.Read(this.temp, 0, remaining);

// We only support 8-bit and 12-bit precision.
if (!this.supportedPrecisions.Contains(this.temp[0]))
{
throw new ImageFormatException("Only 8-Bit and 12-Bit precision supported.");
JpegThrowHelper.ThrowImageFormatException("Only 8-Bit and 12-Bit precision supported.");
}

this.Precision = this.temp[0];
Expand All @@ -740,6 +742,11 @@ private void ProcessStartOfFrameMarker(int remaining, in JpegFileMarker frameMar
ComponentCount = this.temp[5]
};

if (this.Frame.SamplesPerLine == 0 || this.Frame.Scanlines == 0)
{
JpegThrowHelper.ThrowInvalidImageDimensions(this.Frame.SamplesPerLine, this.Frame.Scanlines);
}

this.ImageSizeInPixels = new Size(this.Frame.SamplesPerLine, this.Frame.Scanlines);

int maxH = 0;
Expand Down Expand Up @@ -848,7 +855,7 @@ private void ProcessDefineRestartIntervalMarker(int remaining)
{
if (remaining != 2)
{
throw new ImageFormatException($"DRI has wrong length: {remaining}");
JpegThrowHelper.ThrowImageFormatException($"DRI has wrong length: {remaining}");
}

this.resetInterval = this.ReadUint16();
Expand All @@ -861,7 +868,7 @@ private void ProcessStartOfScanMarker()
{
if (this.Frame is null)
{
throw new ImageFormatException("No readable SOFn (Start Of Frame) marker found.");
JpegThrowHelper.ThrowImageFormatException("No readable SOFn (Start Of Frame) marker found.");
}

int selectorsCount = this.InputStream.ReadByte();
Expand All @@ -882,7 +889,7 @@ private void ProcessStartOfScanMarker()

if (componentIndex < 0)
{
throw new ImageFormatException("Unknown component selector");
JpegThrowHelper.ThrowImageFormatException($"Unknown component selector {componentIndex}.");
}

ref JpegComponent component = ref this.Frame.Components[componentIndex];
Expand Down Expand Up @@ -944,6 +951,11 @@ private ushort ReadUint16()
private Image<TPixel> PostProcessIntoImage<TPixel>()
where TPixel : struct, IPixel<TPixel>
{
if (this.ImageWidth == 0 || this.ImageHeight == 0)
{
JpegThrowHelper.ThrowInvalidImageDimensions(this.ImageWidth, this.ImageHeight);
}

var image = Image.CreateUninitialized<TPixel>(
this.configuration,
this.ImageWidth,
Expand Down
24 changes: 12 additions & 12 deletions src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
internal static class JpegThrowHelper
{
/// <summary>
/// Cold path optimization for throwing <see cref="ImageFormatException"/>-s
/// Cold path optimization for throwing <see cref="ImageFormatException"/>'s.
/// </summary>
/// <param name="errorMessage">The error message for the exception</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowImageFormatException(string errorMessage)
{
throw new ImageFormatException(errorMessage);
}
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage);

[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowBadHuffmanCode()
{
throw new ImageFormatException("Bad Huffman code.");
}
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadHuffmanCode() => throw new ImageFormatException("Bad Huffman code.");

[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNoMergeDcAc() => throw new ImageFormatException("Can't merge DC and AC.");

[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidImageDimensions(int width, int height) => throw new ImageFormatException($"Invalid image dimensions: {width}x{height}.");
}
}
18 changes: 5 additions & 13 deletions tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,14 @@ public void DecodeBaselineJpeg<TPixel>(TestImageProvider<TPixel> provider)
}

[Theory]
[WithFile(TestImages.Jpeg.Issues.CriticalEOF214, PixelTypes.Rgba32)]
public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
// TODO: We need a public ImageDecoderException class in ImageSharp!
Assert.ThrowsAny<Exception>(() => provider.GetImage(JpegDecoder));
}

[Theory]
[WithFile(TestImages.Jpeg.Issues.InvalidJpegThrowsWrongException797, PixelTypes.Rgba32)]
public void LoadingImage_InvalidTagLength_ShouldThrow<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(UnrecoverableTestJpegs), PixelTypes.Rgba32)]
public void UnrecoverableImagesShouldThrowCorrectError<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> => Assert.Throws<ImageFormatException>(() => provider.GetImage());

// TODO: This should actually throw.
[Theory]
[WithFile(TestImages.Jpeg.Issues.AccessViolationException798, PixelTypes.Rgba32)]
[WithFile(TestImages.Jpeg.Issues.Fuzz.AccessViolationException798, PixelTypes.Rgba32)]
public void LoadingImage_BadHuffman_ShouldNotThrow<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> => Assert.NotNull(provider.GetImage());
where TPixel : struct, IPixel<TPixel> => Assert.NotNull(provider.GetImage());
}
}
8 changes: 8 additions & 0 deletions tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ public partial class JpegDecoderTests
TestImages.Jpeg.Issues.OrderedInterleavedProgressive723C
};

public static string[] UnrecoverableTestJpegs = {

TestImages.Jpeg.Issues.CriticalEOF214,
TestImages.Jpeg.Issues.Fuzz.NullReferenceException797,
// TestImages.Jpeg.Issues.Fuzz.AccessViolationException798,
TestImages.Jpeg.Issues.Fuzz.DivideByZeroException821
};

private static readonly Dictionary<string, float> CustomToleranceValues =
new Dictionary<string, float>
{
Expand Down
11 changes: 8 additions & 3 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,13 @@ public static class Issues
public const string OrderedInterleavedProgressive723C = "Jpg/issues/Issue723-Ordered-Interleaved-Progressive-C.jpg";
public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg";
public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg";
public const string InvalidJpegThrowsWrongException797 = "Jpg/issues/Issue797-InvalidImage.jpg";
public const string AccessViolationException798 = "Jpg/issues/Issue798-AccessViolationException.jpg";

public static class Fuzz
{
public const string NullReferenceException797 = "Jpg/issues/fuzz/Issue797-NullReferenceException.jpg";
public const string AccessViolationException798 = "Jpg/issues/fuzz/Issue798-AccessViolationException.jpg";
public const string DivideByZeroException821 = "Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg";
}
}

public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray();
Expand Down Expand Up @@ -235,7 +240,7 @@ public static class Bmp
public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp";
public const string RgbaAlphaBitfields = "Bmp/rgba32abf.bmp";

public static readonly string[] BitFields
public static readonly string[] BitFields
= {
Rgb32bfdef,
Rgb32bf,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.