diff --git a/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs b/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs
index ba22d5d85e..30761328f3 100644
--- a/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs
+++ b/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs
@@ -1,23 +1,33 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Diagnostics.CodeAnalysis;
+
namespace SixLabors.ImageSharp.Compression.Zlib;
internal static class DeflateThrowHelper
{
+ [DoesNotReturn]
public static void ThrowAlreadyFinished() => throw new InvalidOperationException("Finish() already called.");
+ [DoesNotReturn]
public static void ThrowAlreadyClosed() => throw new InvalidOperationException("Deflator already closed.");
+ [DoesNotReturn]
public static void ThrowUnknownCompression() => throw new InvalidOperationException("Unknown compression function.");
+ [DoesNotReturn]
public static void ThrowNotProcessed() => throw new InvalidOperationException("Old input was not completely processed.");
+ [DoesNotReturn]
public static void ThrowNull(string name) => throw new ArgumentNullException(name);
+ [DoesNotReturn]
public static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
+ [DoesNotReturn]
public static void ThrowHeapViolated() => throw new InvalidOperationException("Huffman heap invariant violated.");
+ [DoesNotReturn]
public static void ThrowNoDeflate() => throw new ImageFormatException("Cannot deflate all input.");
}
diff --git a/src/ImageSharp/Compression/Zlib/Deflater.cs b/src/ImageSharp/Compression/Zlib/Deflater.cs
index f001b8a67c..f642ec85a7 100644
--- a/src/ImageSharp/Compression/Zlib/Deflater.cs
+++ b/src/ImageSharp/Compression/Zlib/Deflater.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
@@ -285,7 +284,6 @@ internal sealed class Deflater : IDisposable
if (!this.isDisposed)
{
this.engine.Dispose();
- this.engine = null;
this.isDisposed = true;
}
}
diff --git a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs
index 47bc43f52e..31fa0238bf 100644
--- a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs
+++ b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Buffers;
using System.Runtime.CompilerServices;
@@ -87,7 +86,7 @@ internal sealed unsafe class DeflaterEngine : IDisposable
///
/// The input data for compression.
///
- private byte[] inputBuf;
+ private byte[]? inputBuf;
///
/// The offset into inputBuf, where input data starts.
@@ -222,7 +221,7 @@ internal sealed unsafe class DeflaterEngine : IDisposable
/// The buffer containing input data.
/// The offset of the first byte of data.
/// The number of bytes of data to use as input.
- public void SetInput(byte[] buffer, int offset, int count)
+ public void SetInput(byte[]? buffer, int offset, int count)
{
if (buffer is null)
{
@@ -362,6 +361,8 @@ internal sealed unsafe class DeflaterEngine : IDisposable
more = this.inputEnd - this.inputOff;
}
+ ArgumentNullException.ThrowIfNull(this.inputBuf);
+
Unsafe.CopyBlockUnaligned(
ref this.window.Span[this.strstart + this.lookahead],
ref this.inputBuf[this.inputOff],
@@ -393,11 +394,6 @@ internal sealed unsafe class DeflaterEngine : IDisposable
this.prevMemoryHandle.Dispose();
this.prevMemoryOwner.Dispose();
- this.windowMemoryOwner = null;
- this.headMemoryOwner = null;
- this.prevMemoryOwner = null;
- this.huffman = null;
-
this.isDisposed = true;
}
}
diff --git a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs
index 8c67699085..dc11de4259 100644
--- a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs
+++ b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Buffers;
using System.Runtime.CompilerServices;
@@ -427,10 +426,6 @@ internal sealed unsafe class DeflaterHuffman : IDisposable
this.blTree.Dispose();
this.distTree.Dispose();
- this.Pending = null;
- this.literalTree = null;
- this.blTree = null;
- this.distTree = null;
this.isDisposed = true;
}
}
@@ -977,10 +972,6 @@ internal sealed unsafe class DeflaterHuffman : IDisposable
this.codesMemoryHandle.Dispose();
this.codesMemoryOwner.Dispose();
- this.frequenciesMemoryOwner = null;
- this.lengthsMemoryOwner = null;
- this.codesMemoryOwner = null;
-
this.isDisposed = true;
}
}
diff --git a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs
index cea2fd2721..de818fd8f5 100644
--- a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs
+++ b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Buffers;
using SixLabors.ImageSharp.Memory;
@@ -137,8 +136,6 @@ internal sealed class DeflaterOutputStream : Stream
this.memoryOwner.Dispose();
}
- this.deflater = null;
- this.memoryOwner = null;
this.isDisposed = true;
base.Dispose(disposing);
}
diff --git a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs
index 28febdc118..37e7404e40 100644
--- a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs
+++ b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Buffers;
using System.Runtime.CompilerServices;
@@ -180,7 +179,6 @@ internal sealed unsafe class DeflaterPendingBuffer : IDisposable
{
this.bufferMemoryHandle.Dispose();
this.bufferMemoryOwner.Dispose();
- this.bufferMemoryOwner = null;
this.isDisposed = true;
}
}
diff --git a/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs
index 00c4aed3b1..2e52f84d7b 100644
--- a/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs
+++ b/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Png;
@@ -172,8 +171,6 @@ internal sealed class ZlibDeflateStream : Stream
this.rawStream.WriteByte((byte)(crc & 0xFF));
}
- this.deflateStream = null;
-
base.Dispose(disposing);
this.isDisposed = true;
}
diff --git a/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs
index f9e678605c..06a7c3928c 100644
--- a/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs
+++ b/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
+using System.Diagnostics.CodeAnalysis;
using System.IO.Compression;
using SixLabors.ImageSharp.IO;
@@ -90,7 +90,7 @@ internal sealed class ZlibInflateStream : Stream
///
/// Gets the compressed stream over the deframed inner stream.
///
- public DeflateStream CompressedStream { get; private set; }
+ public DeflateStream? CompressedStream { get; private set; }
///
/// Adds new bytes from a frame found in the original stream.
@@ -98,6 +98,7 @@ internal sealed class ZlibInflateStream : Stream
/// The current remaining data according to the chunk length.
/// Whether the chunk to be inflated is a critical chunk.
/// The .
+ [MemberNotNullWhen(true, nameof(CompressedStream))]
public bool AllocateNewBytes(int bytes, bool isCriticalChunk)
{
this.currentDataRemaining = bytes;
@@ -210,6 +211,7 @@ internal sealed class ZlibInflateStream : Stream
this.isDisposed = true;
}
+ [MemberNotNullWhen(true, nameof(CompressedStream))]
private bool InitializeInflateStream(bool isCriticalChunk)
{
// Read the zlib header : http://tools.ietf.org/html/rfc1950
diff --git a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs
index f00ee1b2a8..8327daf23b 100644
--- a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs
+++ b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
namespace SixLabors.ImageSharp.Diagnostics;
@@ -17,7 +16,7 @@ public static class MemoryDiagnostics
{
private static int totalUndisposedAllocationCount;
- private static UndisposedAllocationDelegate undisposedAllocation;
+ private static UndisposedAllocationDelegate? undisposedAllocation;
private static int undisposedAllocationSubscriptionCounter;
private static readonly object SyncRoot = new();
@@ -50,12 +49,12 @@ public static class MemoryDiagnostics
///
/// Fires when ImageSharp allocates memory from a MemoryAllocator
///
- internal static event Action MemoryAllocated;
+ internal static event Action? MemoryAllocated;
///
/// Fires when ImageSharp releases memory allocated from a MemoryAllocator
///
- internal static event Action MemoryReleased;
+ internal static event Action? MemoryReleased;
///
/// Gets a value indicating the total number of memory resource objects leaked to the finalizer.
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
index 42dcf7200a..e13b26f9a9 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
@@ -26,16 +26,6 @@ internal readonly struct JFifMarker : IEquatable
/// The vertical pixel density.
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
public PixelResolutionUnit DensityUnits { get; }
///
- /// Gets the horizontal pixel density. Must not be zero.
+ /// Gets the horizontal pixel density.
///
public short XDensity { get; }
///
- /// Gets the vertical pixel density. Must not be zero.
+ /// Gets the vertical pixel density.
///
public short YDensity { get; }
@@ -88,12 +78,8 @@ internal readonly struct JFifMarker : IEquatable
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;
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
index 0eb484b94a..51d9bfbced 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
@@ -121,4 +121,10 @@ internal abstract class SpectralConverter
return size;
}
+
+ ///
+ /// Gets a value indicating whether the converter has a pixel buffer.
+ ///
+ /// if the converter has a pixel buffer; otherwise, .
+ public abstract bool HasPixelBuffer();
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
index 4bb58d8a12..d6250127f5 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
@@ -85,6 +85,12 @@ internal class SpectralConverter : SpectralConverter, IDisposable
///
public Configuration Configuration { get; }
+ ///
+ /// Gets a value indicating whether the converter has a pixel buffer.
+ ///
+ /// if the converter has a pixel buffer; otherwise, .
+ public override bool HasPixelBuffer() => this.pixelBuffer is not null;
+
///
/// Gets converted pixel buffer.
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index 77ea4e86fc..ab0521712a 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/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);
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
index 4c377c8783..27c311009c 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
@@ -50,19 +50,21 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
return left > 0 ? left : 0;
}))
{
- deframeStream.AllocateNewBytes(byteCount, true);
- DeflateStream dataStream = deframeStream.CompressedStream;
-
- int totalRead = 0;
- while (totalRead < buffer.Length)
+ if (deframeStream.AllocateNewBytes(byteCount, true))
{
- int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead);
- if (bytesRead <= 0)
+ DeflateStream? dataStream = deframeStream.CompressedStream;
+
+ int totalRead = 0;
+ while (totalRead < buffer.Length)
{
- break;
- }
+ int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead);
+ if (bytesRead <= 0)
+ {
+ break;
+ }
- totalRead += bytesRead;
+ totalRead += bytesRead;
+ }
}
}
diff --git a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs
index 547f67d6a7..6f48c56696 100644
--- a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs
+++ b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
// Port of BCL internal utility:
// https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs
@@ -15,8 +14,8 @@ namespace SixLabors.ImageSharp.Memory.Internals;
///
internal sealed class Gen2GcCallback : CriticalFinalizerObject
{
- private readonly Func callback0;
- private readonly Func
public sealed class Owned : MemoryGroup, IEnumerable>
{
- private IMemoryOwner[] memoryOwners;
- private RefCountedMemoryLifetimeGuard groupLifetimeGuard;
+ private IMemoryOwner[]? memoryOwners;
+ private RefCountedMemoryLifetimeGuard? groupLifetimeGuard;
public Owned(IMemoryOwner[] memoryOwners, int bufferLength, long totalLength, bool swappable)
: base(bufferLength, totalLength)
@@ -149,7 +149,7 @@ internal abstract partial class MemoryGroup
}
else
{
- foreach (IMemoryOwner memoryOwner in this.memoryOwners)
+ foreach (IMemoryOwner memoryOwner in this.memoryOwners!)
{
memoryOwner.Dispose();
}
@@ -161,6 +161,7 @@ internal abstract partial class MemoryGroup
}
[MethodImpl(InliningOptions.ShortMethod)]
+ [MemberNotNull(nameof(memoryOwners))]
private void EnsureNotDisposed()
{
if (this.memoryOwners is null)
@@ -170,6 +171,7 @@ internal abstract partial class MemoryGroup
}
[MethodImpl(MethodImplOptions.NoInlining)]
+ [DoesNotReturn]
private static void ThrowObjectDisposedException() => throw new ObjectDisposedException(nameof(MemoryGroup));
// When the MemoryGroup points to multiple buffers via `groupLifetimeGuard`,
diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs
index 1ef30e354c..d63fd2076c 100644
--- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs
+++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs
@@ -1,9 +1,9 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-#nullable disable
using System.Buffers;
using System.Collections;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory.Internals;
@@ -41,7 +41,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable
///
public bool IsValid { get; private set; } = true;
- public MemoryGroupView View { get; private set; }
+ public MemoryGroupView View { get; private set; } = null!;
///
public abstract Memory this[int index] { get; }
@@ -150,7 +150,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable
long totalLengthInElements,
int bufferAlignmentInElements,
AllocationOptions options,
- out MemoryGroup memoryGroup)
+ [NotNullWhen(true)] out MemoryGroup? memoryGroup)
{
Guard.NotNull(pool, nameof(pool));
Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements));
@@ -188,7 +188,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable
bufferCount++;
}
- UnmanagedMemoryHandle[] arrays = pool.Rent(bufferCount);
+ UnmanagedMemoryHandle[]? arrays = pool.Rent(bufferCount);
if (arrays == null)
{
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
index aa88242ce4..b5a7245292 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
@@ -54,6 +54,8 @@ public class DecodeJpegParseStreamOnly
{
}
+ public override bool HasPixelBuffer() => throw new NotImplementedException();
+
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)
{
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs
index 3890c20e93..3b7e20eb4e 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs
@@ -46,15 +46,6 @@ public class JFifMarkerTests
Assert.Equal(default, marker);
}
- [Fact]
- public void MarkerIgnoresCorrectHeaderButInvalidDensities()
- {
- bool isJFif = JFifMarker.TryParse(this.bytes3, out JFifMarker marker);
-
- Assert.False(isJFif);
- Assert.Equal(default, marker);
- }
-
[Fact]
public void MarkerEqualityIsCorrect()
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
index 1d5a7e0ff8..425d12497c 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
+++ b/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(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using Image image = provider.GetImage(JpegDecoder.Instance);
+ image.DebugSave(provider);
+ image.CompareToOriginal(provider);
+ }
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
index 58347a0724..805ee586a8 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
+++ b/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;
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 29223b1fe0..22a48ebee4 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/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
{
diff --git a/tests/Images/Input/Jpg/issues/issue-2315.jpg b/tests/Images/Input/Jpg/issues/issue-2315.jpg
new file mode 100644
index 0000000000..fe3001eddc
--- /dev/null
+++ b/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