From 8f3658da6c0040198c01dbf892a9ea77d0556407 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 17 Feb 2019 22:05:16 +1100 Subject: [PATCH] Jpeg Fuzz Fixes (#836) * Nomalize jpeg exceptions. Fix #821 * Fix #822 * Fix #823 * Check for correct QT index. Touch #824 * Check DHT props. Touch #824 * Limit sampling factors to 1 & 2. Touch #824 * Add already fixed image 4. Touch #824 * Check for excessive code lengths. Touch #824 * Add already fixed image 6. Touch #824 * Lint progressive scan details. Touch #824 * Add already fixed image 8. Fix #824 * Remove duplicate per-block checks * Add already fixed image 1. Touch #825 * Don't throw on bad JFIF density units. * Add already fixed image 3. Touch #825 * Add already fixed image 4. Fix #825 * Check SOFn marker length. Touch #826 * Add already fixed image 2. Touch #826 * Add already fixed image 3. Fix #826 * Add fixed already fixed image. Fix #827 * Revert unneeded bounds check introduced in #804 --- .../Jpeg/Components/Decoder/HuffmanTable.cs | 22 ++--- .../Jpeg/Components/Decoder/JFifMarker.cs | 19 ++-- .../Jpeg/Components/Decoder/JpegComponent.cs | 21 ++++ .../Jpeg/Components/Decoder/JpegFrame.cs | 2 +- .../Jpeg/Components/Decoder/ScanDecoder.cs | 62 ++++++++++-- .../Formats/Jpeg/JpegDecoderCore.cs | 92 ++++++++++++++---- .../Formats/Jpeg/JpegThrowHelper.cs | 35 ++++--- .../Formats/Jpg/JpegDecoderTests.Baseline.cs | 19 +--- .../Formats/Jpg/JpegDecoderTests.Images.cs | 28 ++++++ tests/ImageSharp.Tests/TestImages.cs | 29 +++++- tests/Images/External | 2 +- ...ticalEOF .jpg => Issue214-CriticalEOF.jpg} | Bin .../Issue797-NullReferenceException.jpg} | Bin .../Issue798-AccessViolationException.jpg | Bin .../fuzz/Issue821-DivideByZeroException.jpg | Bin 0 -> 397 bytes .../fuzz/Issue822-DivideByZeroException.jpg | Bin 0 -> 397 bytes .../fuzz/Issue823-NullReferenceException.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-A.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-B.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-C.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-D.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-E.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-F.jpg | Bin 0 -> 411 bytes .../Issue824-IndexOutOfRangeException-G.jpg | Bin 0 -> 308 bytes .../Issue824-IndexOutOfRangeException-H.jpg | Bin 0 -> 308 bytes ...Issue825-ArgumentOutOfRangeException-A.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-B.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-C.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-D.jpg | Bin 0 -> 380 bytes .../fuzz/Issue826-ArgumentException-A.jpg | Bin 0 -> 397 bytes .../fuzz/Issue826-ArgumentException-B.jpg | Bin 0 -> 397 bytes .../fuzz/Issue826-ArgumentException-C.jpg | Bin 0 -> 409 bytes .../Issue827-AccessViolationException.jpg | Bin 0 -> 397 bytes 33 files changed, 246 insertions(+), 85 deletions(-) rename tests/Images/Input/Jpg/issues/{Issue214-CriticalEOF .jpg => Issue214-CriticalEOF.jpg} (100%) rename tests/Images/Input/Jpg/issues/{Issue797-InvalidImage.jpg => fuzz/Issue797-NullReferenceException.jpg} (100%) rename tests/Images/Input/Jpg/issues/{ => fuzz}/Issue798-AccessViolationException.jpg (100%) create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-D.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-F.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-G.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 9e11981b12..90b3624651 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -50,10 +50,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The huffman values public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) { - // We do some bounds checks in the code here to protect against AccessViolationExceptions - const int HuffCodeLength = 257; - const int MaxSizeLength = HuffCodeLength - 1; - using (IMemoryOwner huffcode = memoryAllocator.Allocate(HuffCodeLength)) + const int Length = 257; + using (IMemoryOwner huffcode = memoryAllocator.Allocate(Length)) { ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths); @@ -65,7 +63,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (short i = 1; i < 17; i++) { byte length = Unsafe.Add(ref codeLengthsRef, i); - for (short j = 0; j < length && x < MaxSizeLength; j++) + for (short j = 0; j < length; j++) { Unsafe.Add(ref sizesRef, x++) = i; } @@ -86,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder Unsafe.Add(ref valOffsetRef, k) = (int)(si - code); if (Unsafe.Add(ref sizesRef, si) == k) { - while (Unsafe.Add(ref sizesRef, si) == k && si < HuffCodeLength) + while (Unsafe.Add(ref sizesRef, si) == k) { Unsafe.Add(ref huffcodeRef, si++) = (short)code++; } @@ -103,19 +101,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // Generate non-spec lookup tables to speed up decoding. const int FastBits = ScanDecoder.FastBits; ref byte lookaheadRef = ref this.Lookahead[0]; - const uint MaxFastLength = 1 << FastBits; - Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, MaxFastLength); // Flag for non-accelerated + Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, 1 << FastBits); // Flag for non-accelerated for (int i = 0; i < si; i++) { int size = Unsafe.Add(ref sizesRef, i); if (size <= FastBits) { - int huffCode = Unsafe.Add(ref huffcodeRef, i) << (FastBits - size); - int max = 1 << (FastBits - size); - for (int left = 0; left < max; left++) + int fastOffset = FastBits - size; + int fastCode = Unsafe.Add(ref huffcodeRef, i) << fastOffset; + int fastMax = 1 << fastOffset; + for (int left = 0; left < fastMax; left++) { - Unsafe.Add(ref lookaheadRef, huffCode + left) = (byte)i; + Unsafe.Add(ref lookaheadRef, fastCode + left) = (byte)i; } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index c51a2f4da5..76f0e2cb51 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -27,12 +27,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The vertical pixel density private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity) { - Guard.MustBeGreaterThan(xDensity, 0, nameof(xDensity)); - Guard.MustBeGreaterThan(yDensity, 0, nameof(yDensity)); - Guard.MustBeBetweenOrEqualTo(densityUnits, 0, 2, nameof(densityUnits)); + if (xDensity <= 0) + { + JpegThrowHelper.ThrowImageFormatException($"X-Density {xDensity} must be greater than 0."); + } + + if (yDensity <= 0) + { + JpegThrowHelper.ThrowImageFormatException($"Y-Density {yDensity} must be greater than 0."); + } this.MajorVersion = majorVersion; this.MinorVersion = minorVersion; + + // LibJpeg and co will simply cast and not try to enforce a range. this.DensityUnits = (PixelResolutionUnit)densityUnits; this.XDensity = xDensity; this.YDensity = yDensity; @@ -104,10 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - public override bool Equals(object obj) - { - return obj is JFifMarker other && this.Equals(other); - } + public override bool Equals(object obj) => obj is JFifMarker other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs index cfed5d535f..ac24f4ca58 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs @@ -21,9 +21,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.memoryAllocator = memoryAllocator; this.Frame = frame; this.Id = id; + + // Valid sampling factors are 1..2 + if (horizontalFactor == 0 + || verticalFactor == 0 + || horizontalFactor > 2 + || verticalFactor > 2) + { + JpegThrowHelper.ThrowBadSampling(); + } + this.HorizontalSamplingFactor = horizontalFactor; this.VerticalSamplingFactor = verticalFactor; this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor); + + if (quantizationTableIndex > 3) + { + JpegThrowHelper.ThrowBadQuantizationTable(); + } + this.QuantizationTableIndex = quantizationTableIndex; this.Index = index; } @@ -110,6 +126,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder JpegComponent c0 = this.Frame.Components[0]; this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); + if (this.SubSamplingDivisors.Width == 0 || this.SubSamplingDivisors.Height == 0) + { + JpegThrowHelper.ThrowBadSampling(); + } + int totalNumberOfBlocks = blocksPerColumnForMcu * (blocksPerLineForMcu + 1); int width = this.WidthInBlocks + 1; int height = totalNumberOfBlocks / width; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs index 36a3dc2d26..33a7c68baf 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { for (int i = 0; i < this.Components.Length; i++) { - this.Components[i].Dispose(); + this.Components[i]?.Dispose(); } this.Components = null; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs index a1c1b023e4..070652a9f9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs @@ -270,8 +270,60 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } + private void CheckProgressiveData() + { + // Validate successive scan parameters. + // Logic has been adapted from libjpeg. + // See Table B.3 – Scan header parameter size and values. itu-t81.pdf + bool invalid = false; + if (this.spectralStart == 0) + { + if (this.spectralEnd != 0) + { + invalid = true; + } + } + else + { + // Need not check Ss/Se < 0 since they came from unsigned bytes. + if (this.spectralEnd < this.spectralStart || this.spectralEnd > 63) + { + invalid = true; + } + + // AC scans may have only one component. + if (this.componentsLength != 1) + { + invalid = true; + } + } + + if (this.successiveHigh != 0) + { + // Successive approximation refinement scan: must have Al = Ah-1. + if (this.successiveHigh - 1 != this.successiveLow) + { + invalid = true; + } + } + + // TODO: How does this affect 12bit jpegs. + // According to libjpeg the range covers 8bit only? + if (this.successiveLow > 13) + { + invalid = true; + } + + if (invalid) + { + JpegThrowHelper.ThrowBadProgressiveScan(this.spectralStart, this.spectralEnd, this.successiveHigh, this.successiveLow); + } + } + private void ParseProgressiveData() { + this.CheckProgressiveData(); + if (this.componentsLength == 1) { this.ParseProgressiveDataNonInterleaved(); @@ -483,11 +535,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref Block8x8 block, ref HuffmanTable dcTable) { - if (this.spectralEnd != 0) - { - JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC."); - } - this.CheckBits(); ref short blockDataRef = ref Unsafe.As(ref block); @@ -518,11 +565,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref HuffmanTable acTable, ref short fastACRef) { - if (this.spectralStart == 0) - { - JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC."); - } - ref short blockDataRef = ref Unsafe.As(ref block); if (this.successiveHigh == 0) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 06c844d58e..9bcfd9ff64 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg 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); @@ -419,7 +419,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg : 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; } /// @@ -646,6 +647,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg bool done = false; remaining--; int quantizationTableSpec = this.InputStream.ReadByte(); + int tableIndex = quantizationTableSpec & 15; + + // Max index. 4 Tables max. + if (tableIndex > 3) + { + JpegThrowHelper.ThrowBadQuantizationTable(); + } switch (quantizationTableSpec >> 4) { @@ -661,7 +669,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, 64); remaining -= 64; - ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15]; + ref Block8x8F table = ref this.QuantizationTables[tableIndex]; for (int j = 0; j < 64; j++) { table[j] = this.temp[j]; @@ -681,7 +689,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, 128); remaining -= 128; - ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15]; + ref Block8x8F table = ref this.QuantizationTables[tableIndex]; for (int j = 0; j < 64; j++) { table[j] = (this.temp[2 * j] << 8) | this.temp[(2 * j) + 1]; @@ -690,7 +698,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg break; default: - throw new ImageFormatException("Bad Tq index value"); + JpegThrowHelper.ThrowBadQuantizationTable(); + break; } if (done) @@ -701,7 +710,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (remaining != 0) { - throw new ImageFormatException("DQT has wrong length"); + JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining); } this.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); @@ -717,15 +726,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { 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); + // Read initial marker definitions. + const int length = 6; + this.InputStream.Read(this.temp, 0, length); // 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]; @@ -740,22 +751,35 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ComponentCount = this.temp[5] }; - this.ImageSizeInPixels = new Size(this.Frame.SamplesPerLine, this.Frame.Scanlines); - - int maxH = 0; - int maxV = 0; - int index = 6; + 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); this.ComponentCount = this.Frame.ComponentCount; if (!metadataOnly) { + remaining -= length; + + const int componentBytes = 3; + if (remaining > this.ComponentCount * componentBytes) + { + JpegThrowHelper.ThrowBadMarker("SOFn", remaining); + } + + this.InputStream.Read(this.temp, 0, remaining); + // No need to pool this. They max out at 4 this.Frame.ComponentIds = new byte[this.ComponentCount]; this.Frame.ComponentOrder = new byte[this.ComponentCount]; this.Frame.Components = new JpegComponent[this.ComponentCount]; this.ColorSpace = this.DeduceJpegColorSpace(); + int maxH = 0; + int maxV = 0; + int index = 0; for (int i = 0; i < this.ComponentCount; i++) { byte hv = this.temp[index + 1]; @@ -777,7 +801,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.Frame.Components[i] = component; this.Frame.ComponentIds[i] = component.Id; - index += 3; + index += componentBytes; } this.Frame.MaxHorizontalFactor = maxH; @@ -795,12 +819,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessDefineHuffmanTablesMarker(int remaining) { + int length = remaining; + using (IManagedByteBuffer huffmanData = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean)) { ref byte huffmanDataRef = ref MemoryMarshal.GetReference(huffmanData.GetSpan()); for (int i = 2; i < remaining;) { byte huffmanTableSpec = (byte)this.InputStream.ReadByte(); + int tableType = huffmanTableSpec >> 4; + int tableIndex = huffmanTableSpec & 15; + + // Types 0..1 DC..AC + if (tableType > 1) + { + JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table type."); + } + + // Max tables of each type + if (tableIndex > 3) + { + JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table index."); + } + this.InputStream.Read(huffmanData.Array, 0, 16); using (IManagedByteBuffer codeLengths = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(17, AllocationOptions.Clean)) @@ -813,15 +854,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg codeLengthSum += Unsafe.Add(ref codeLengthsRef, j) = Unsafe.Add(ref huffmanDataRef, j - 1); } + length -= 17; + + if (codeLengthSum > 256 || codeLengthSum > length) + { + JpegThrowHelper.ThrowImageFormatException("Huffman table has excessive length."); + } + using (IManagedByteBuffer huffmanValues = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean)) { this.InputStream.Read(huffmanValues.Array, 0, codeLengthSum); i += 17 + codeLengthSum; - int tableType = huffmanTableSpec >> 4; - int tableIndex = huffmanTableSpec & 15; - this.BuildHuffmanTable( tableType == 0 ? this.dcHuffmanTables : this.acHuffmanTables, tableIndex, @@ -848,7 +893,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (remaining != 2) { - throw new ImageFormatException($"DRI has wrong length: {remaining}"); + JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DRI), remaining); } this.resetInterval = this.ReadUint16(); @@ -861,7 +906,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { 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(); @@ -882,7 +927,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (componentIndex < 0) { - throw new ImageFormatException("Unknown component selector"); + JpegThrowHelper.ThrowImageFormatException($"Unknown component selector {componentIndex}."); } ref JpegComponent component = ref this.Frame.Components[componentIndex]; @@ -944,6 +989,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private Image PostProcessIntoImage() where TPixel : struct, IPixel { + if (this.ImageWidth == 0 || this.ImageHeight == 0) + { + JpegThrowHelper.ThrowInvalidImageDimensions(this.ImageWidth, this.ImageHeight); + } + var image = Image.CreateUninitialized( this.configuration, this.ImageWidth, diff --git a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs index c7f3666604..b30da28c45 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs @@ -8,19 +8,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg internal static class JpegThrowHelper { /// - /// Cold path optimization for throwing -s + /// Cold path optimization for throwing 's. /// - /// The error message for the exception - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowImageFormatException(string errorMessage) - { - throw new ImageFormatException(errorMessage); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowBadHuffmanCode() - { - throw new ImageFormatException("Bad Huffman code."); - } + /// The error message for the exception. + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadMarker(string marker, int length) => throw new ImageFormatException($"Marker {marker} has bad length {length}."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadQuantizationTable() => throw new ImageFormatException("Bad Quantization Table index."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadHuffmanCode() => throw new ImageFormatException("Bad Huffman code."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadSampling() => throw new ImageFormatException("Bad sampling factor."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadProgressiveScan(int ss, int se, int ah, int al) => throw new ImageFormatException($"Invalid progressive parameters Ss={ss} Se={se} Ah={ah} Al={al}."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowInvalidImageDimensions(int width, int height) => throw new ImageFormatException($"Invalid image dimensions: {width}x{height}."); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index 1c9d207cd1..31a5a0eeb0 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -35,22 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } [Theory] - [WithFile(TestImages.Jpeg.Issues.CriticalEOF214, PixelTypes.Rgba32)] - public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow(TestImageProvider provider) - where TPixel : struct, IPixel - { - // TODO: We need a public ImageDecoderException class in ImageSharp! - Assert.ThrowsAny(() => provider.GetImage(JpegDecoder)); - } - - [Theory] - [WithFile(TestImages.Jpeg.Issues.InvalidJpegThrowsWrongException797, PixelTypes.Rgba32)] - public void LoadingImage_InvalidTagLength_ShouldThrow(TestImageProvider provider) + [WithFileCollection(nameof(UnrecoverableTestJpegs), PixelTypes.Rgba32)] + public void UnrecoverableImagesShouldThrowCorrectError(TestImageProvider provider) where TPixel : struct, IPixel => Assert.Throws(() => provider.GetImage()); - - [Theory] - [WithFile(TestImages.Jpeg.Issues.AccessViolationException798, PixelTypes.Rgba32)] - public void LoadingImage_BadHuffman_ShouldNotThrow(TestImageProvider provider) - where TPixel : struct, IPixel => Assert.NotNull(provider.GetImage()); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 9f34d7d09b..ff49de2481 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -31,6 +31,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifGetString750Load, TestImages.Jpeg.Issues.ExifGetString750Transform, + // LibJpeg can open this despite the invalid desity units. + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B, + // High depth images TestImages.Jpeg.Baseline.Testorig12bit, }; @@ -54,6 +57,31 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg 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, + TestImages.Jpeg.Issues.Fuzz.DivideByZeroException822, + TestImages.Jpeg.Issues.Fuzz.NullReferenceException823, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824A, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824B, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824D, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824E, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824F, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824G, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824H, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825A, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825C, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825D, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826A, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826B, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826C, + TestImages.Jpeg.Issues.Fuzz.AccessViolationException827 + }; + private static readonly Dictionary CustomToleranceValues = new Dictionary { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index e28caf6277..c99fe8d652 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -172,8 +172,31 @@ namespace SixLabors.ImageSharp.Tests 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 const string DivideByZeroException822 = "Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg"; + public const string NullReferenceException823 = "Jpg/issues/fuzz/Issue823-NullReferenceException.jpg"; + public const string IndexOutOfRangeException824A = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg"; + public const string IndexOutOfRangeException824B = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg"; + public const string IndexOutOfRangeException824C = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg"; + public const string IndexOutOfRangeException824D = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-D.jpg"; + public const string IndexOutOfRangeException824E = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg"; + public const string IndexOutOfRangeException824F = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-F.jpg"; + public const string IndexOutOfRangeException824G = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-G.jpg"; + public const string IndexOutOfRangeException824H = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg"; + public const string ArgumentOutOfRangeException825A = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg"; + public const string ArgumentOutOfRangeException825B = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg"; + public const string ArgumentOutOfRangeException825C = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg"; + public const string ArgumentOutOfRangeException825D = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg"; + public const string ArgumentException826A = "Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg"; + public const string ArgumentException826B = "Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg"; + public const string ArgumentException826C = "Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg"; + public const string AccessViolationException827 = "Jpg/issues/fuzz/Issue827-AccessViolationException.jpg"; + } } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); @@ -236,7 +259,7 @@ namespace SixLabors.ImageSharp.Tests 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, diff --git a/tests/Images/External b/tests/Images/External index 32dc8aec11..c4098e463a 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 32dc8aec1109b681f056264e6bde1f3a76f08aba +Subproject commit c4098e463ab0e7128ae196b7f963369271df8fd3 diff --git a/tests/Images/Input/Jpg/issues/Issue214-CriticalEOF .jpg b/tests/Images/Input/Jpg/issues/Issue214-CriticalEOF.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue214-CriticalEOF .jpg rename to tests/Images/Input/Jpg/issues/Issue214-CriticalEOF.jpg diff --git a/tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue797-NullReferenceException.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg rename to tests/Images/Input/Jpg/issues/fuzz/Issue797-NullReferenceException.jpg diff --git a/tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue798-AccessViolationException.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg rename to tests/Images/Input/Jpg/issues/fuzz/Issue798-AccessViolationException.jpg diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ace30e1fbcab974ea2ec4888b441c4ee75b637e GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOLaWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@g9Ey3 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4378f429e6a96238859432baffd198ab0854d53e GIT binary patch literal 397 zcmex=Wcj9NnTq1L7-AG*#r~ReW8)bK;5r z|LgxF08lMsXjD{1X2t8Krq};~5)A)2LDKag0t6U@AvA~yXCWAjK*0kHf*cGA3<}JQ zN(@YbjLcWN?GIo1n54W_dVT2R+L!l=dHyr-2On+QzLjaZy&&WNBMjmU49tuiKvyFG zBNH=FLREl~fr){YnS~i91LO+|DH?8cESkiem~>IeC=jSjj1dT6Dj+l?NV~WoJ6z&_ z14x3AK~VAkEe2&~kU7kP4E7AyzlG-ByO)1Qd-L7Ah>whc^)1`7-fa4P`|R(|C{wpv qH%vEuI=zjlBv?kR{NCK>hSpod(|6t3IC~OaUnySO;liH(|0V#OGO4)$ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e18bbe231031fe2c659fe9e1c84c0fba8a9855c4 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GjgRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@1R}cp literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..49e4d04e7864844e1d2709897d277a9531c889d3 GIT binary patch literal 397 zcmex=k#+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@oV&V& literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac2e882a45e3af1487549fbf420e78ecfebb4450 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO635aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@l*_t+ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69b7c030a231d278c23915bb81a7cc79a3c83328 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYT*Sa6$jB_n`2PrlI0FMSBLfOx zWMT$Ns0uJLFfp()voOOXfqX$BMZ=AbMU$8llP)S51p<|c0ey!_#-&**JUB)o%O4S3V{wZez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRBB)nWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@0;0P7 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b6e7ed11e5a08907d0836f30fd80b2ff8d2bdc13 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvk%<8r zFfuU%B~%3%8JHMYnOT@&azMVIkfPy6$D&EhiAfigi~@nm#DG3!gsFhgj3Djeg6I;A z41$XPZ!z#NgUn$TWUyzr{w*~3-o5-g+MDm@MSNrotZ&(t^=8xW+h>1wMwzez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYWMW_vWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(qV`sE%b|0LlsqDH?8cESkiem~>IeC=jSg4Crr|X}8b*2I*u3 z873}>Bmp*$kwH-L|1Aa{pyf=0%z_N|4A;Mf=H9!Pe@A=s-Mom8jDhtn+p^wl`VBOu zGs@KM)(z85pU!V%DhZZRE5A4QxuNye@bq1GHqM@OwcGyim5)ivTcy{BPOg1ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO645aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N U76T8^IwnD8?ad4f5g!=?0mUSVMgRZ+ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54bdc29409fdc850dea876308205440152acef7a GIT binary patch literal 308 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO645aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N V76T8^IwnEpUknVtB0e$(0szaIid+By literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a47a0057d8134342f32842d17ce99b8b08a9fba0 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@Rie85 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffc801787a5a1b2108acf9513279dd7d994e2f3f GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJ7=Zw$0zxx_w2KR(OE5AB zD*nI4zyq|7Nsw8P!Jgszx6s^s_ww&(Z@!xs@sTmGzGYk1n@zuOpZ(n#W$Je8hUunH zr?)Yc1k0$E-<$i~(0Xfl`mQ@0XHUA?ZGZU6$0X&g((6Mf*S@@0%=4dtKlo_d_N`3Q O?G>->aAD8?e-i*vBD(wl literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfd42e6f539654f35e8cdd503b0e0b6d86f76290 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeKBU{GLYRAOKfWMmd({C|W&oPmLv5h#iT z7@3%X5~>1>3``8H%q+|>DIi}^NYQYkW6>n$#H5Q#Mu9+OVnCmw>j!BU7etp}WDr#R ze~W#!}V{Wx%ckn-_hQDH!tENV_<#DwyZase&0U(yEDqv?bZ#`O`lG0 zV=4)jQ7gYU_qn0<*6{RQcQ($RbhX?5@Rg5A%3Gz^hfc12d9Rq~KLda8(YEbdnWoz- MUfbcqp8x+Q0CV%YTmS$7 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg new file mode 100644 index 0000000000000000000000000000000000000000..58e96a2b1f66fbdb6d16af3fe6ae76c5ffa8809c GIT binary patch literal 380 zcmex=ez+{VquD8S9pEh;o1zTpH@MP6RT*Y!Im zp7@Ufek1XK`WQo_qAD^gUN<$pMv@?fd4NHXgF%5oftgW>fk}{&`6J{1BMjmU49tuS zD1ecP87QGDz{tSFz{<=b3zG!$1%(t1H#!zgVoprDsALofR3--W9J+pxc5y+tgelMf zpb|y~LB;<}g3N-8>=~|q3(dWEFaM7A=DT?j9~lGdTefAr+4TGN+25T}rf#=xm~Q%X zdK*(ou#8&yy}8c~t+$4!@4B;b_N1%b_J^-rPhwzUV31xPI=S}cy<(pKjQqhz+qQ3I Pnr^RnZHEhc{{Nc**7vOl literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aed67b2866003fa24b2bcfe4c1f03791282e75c5 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO6A5aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@2co+C literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e320cf62d27e39ad3c6062b1eb2ae60bc560900d GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd(1Ugrofq|Kk0R=EJ zF#{!31sEBa7+9HEm|>DYzMznz;YP=zNz92!7nO_xfy%^yK1J6L(k?EDF2TqksQCXD z0}s$TCP8LF2789<-$HZm-OInDz4>ll#7D-!`j%~3Z#MnDefD=}l&RaT8>X8+o!-V& z5-g)uesAt`L+h>K>AUW1oIUAkxBcNOACr`~O0N%{T>J7~G0%Sn{@|l++qW`Jw^zKj K!-YNn|4jg8`?_EN literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54ccb95c3db9a30a07cb2cdaead4e180732f35e5 GIT binary patch literal 409 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7@Uidll#7D-! z`j%~3Z#Mk~Iq961|97vL=RX5~@X@yITbZWYD_+~-!k+*CCIE7*xn}?X literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5d770c3b481dc82dac187aabc7c4033a5ff499ff GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oS}i4kpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@{FA!; literal 0 HcmV?d00001