diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/BufferProcessor.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/BufferProcessor.cs
index a8ceb7080..6dc3c012c 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/BufferProcessor.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/BufferProcessor.cs
@@ -50,7 +50,7 @@ namespace ImageSharp.Formats.Jpg
public byte[] Temp { get; }
///
- /// Gets or sets the value indicating whether an unexpected EOF reached in .
+ /// Gets or sets a value indicating whether an unexpected EOF reached in .
///
public bool UnexpectedEndOfStreamReached { get; set; }
@@ -58,8 +58,8 @@ namespace ImageSharp.Formats.Jpg
/// If errorCode indicates unexpected EOF, sets to true and returns false.
/// Calls and returns true otherwise.
///
- ///
- ///
+ /// The
+ /// indicating whether everything is OK
public bool CheckEOFEnsureNoError(DecoderErrorCode errorCode)
{
if (errorCode == DecoderErrorCode.UnexpectedEndOfStream)
@@ -67,10 +67,28 @@ namespace ImageSharp.Formats.Jpg
this.UnexpectedEndOfStreamReached = true;
return false;
}
+
errorCode.EnsureNoError();
return true;
}
+ ///
+ /// If errorCode indicates unexpected EOF, sets to true and returns false.
+ /// Returns true otherwise.
+ ///
+ /// The
+ /// indicating whether everything is OK
+ public bool CheckEOF(DecoderErrorCode errorCode)
+ {
+ if (errorCode == DecoderErrorCode.UnexpectedEndOfStream)
+ {
+ this.UnexpectedEndOfStreamReached = true;
+ return false;
+ }
+
+ return true;
+ }
+
///
/// Dispose
///
diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
index 7968491f9..472720f8f 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
@@ -198,7 +198,10 @@ namespace ImageSharp.Formats.Jpg
int blockIndex = this.GetBlockIndex(decoder);
this.data.Block = decoder.DecodedBlocks[this.ComponentIndex][blockIndex].Block;
- this.DecodeBlock(decoder, scanIndex);
+ if (!decoder.BufferProcessor.UnexpectedEndOfStreamReached)
+ {
+ this.DecodeBlock(decoder, scanIndex);
+ }
// Store the decoded block
DecodedBlockMemento[] blocks = decoder.DecodedBlocks[this.ComponentIndex];
@@ -215,17 +218,22 @@ namespace ImageSharp.Formats.Jpg
{
// A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
// but this one assumes well-formed input, and hence the restart marker follows immediately.
- decoder.BufferProcessor.ReadFull(decoder.Temp, 0, 2);
-
- if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst)
+ if (!decoder.BufferProcessor.UnexpectedEndOfStreamReached)
{
- throw new ImageFormatException("Bad RST marker");
- }
+ DecoderErrorCode errorCode = decoder.BufferProcessor.ReadFullUnsafe(decoder.Temp, 0, 2);
+ if (decoder.BufferProcessor.CheckEOFEnsureNoError(errorCode))
+ {
+ if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst)
+ {
+ throw new ImageFormatException("Bad RST marker");
+ }
- expectedRst++;
- if (expectedRst == JpegConstants.Markers.RST7 + 1)
- {
- expectedRst = JpegConstants.Markers.RST0;
+ expectedRst++;
+ if (expectedRst == JpegConstants.Markers.RST7 + 1)
+ {
+ expectedRst = JpegConstants.Markers.RST0;
+ }
+ }
}
// Reset the Huffman decoder.
@@ -362,7 +370,10 @@ namespace ImageSharp.Formats.Jpg
errorCode = decoder.BufferProcessor.DecodeHuffmanUnsafe(
ref decoder.HuffmanTrees[huffmanIndex],
out value);
- errorCode.EnsureNoEOF();
+ if (!decoder.BufferProcessor.CheckEOF(errorCode))
+ {
+ return;
+ }
if (value > 16)
{
@@ -371,7 +382,10 @@ namespace ImageSharp.Formats.Jpg
int deltaDC;
errorCode = decoder.BufferProcessor.ReceiveExtendUnsafe(value, out deltaDC);
- errorCode.EnsureNoError();
+ if (!decoder.BufferProcessor.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
this.pointers.Dc[this.ComponentIndex] += deltaDC;
@@ -390,7 +404,10 @@ namespace ImageSharp.Formats.Jpg
{
int value;
errorCode = decoder.BufferProcessor.DecodeHuffmanUnsafe(ref decoder.HuffmanTrees[huffmannIdx], out value);
- errorCode.EnsureNoEOF();
+ if (!decoder.BufferProcessor.CheckEOF(errorCode))
+ {
+ return;
+ }
int val0 = value >> 4;
int val1 = value & 0x0f;
@@ -404,7 +421,10 @@ namespace ImageSharp.Formats.Jpg
int ac;
errorCode = decoder.BufferProcessor.ReceiveExtendUnsafe(val1, out ac);
- errorCode.EnsureNoError();
+ if (!decoder.BufferProcessor.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
// b[Unzig[zig]] = ac << al;
Block8x8F.SetScalarAt(b, this.pointers.Unzig[zig], ac << this.al);
@@ -417,7 +437,10 @@ namespace ImageSharp.Formats.Jpg
if (val0 != 0)
{
errorCode = this.DecodeEobRun(val0, ref decoder.BufferProcessor);
- errorCode.EnsureNoError();
+ if (!decoder.BufferProcessor.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
}
this.eobRun--;
@@ -428,7 +451,7 @@ namespace ImageSharp.Formats.Jpg
}
}
}
- }
+ }
}
private DecoderErrorCode DecodeEobRun(int count, ref BufferProcessor decoder)
@@ -516,10 +539,10 @@ namespace ImageSharp.Formats.Jpg
///
/// Decodes a successive approximation refinement block, as specified in section G.1.2.
///
- /// The decoder instance
+ /// The instance
/// The Huffman tree
/// The low transform offset
- private void Refine(ref BufferProcessor decoder, ref HuffmanTree h, int delta)
+ private void Refine(ref BufferProcessor bp, ref HuffmanTree h, int delta)
{
Block8x8F* b = this.pointers.Block;
@@ -532,8 +555,12 @@ namespace ImageSharp.Formats.Jpg
}
bool bit;
- DecoderErrorCode errorCode = decoder.DecodeBitUnsafe(out bit);
- errorCode.EnsureNoError();
+ DecoderErrorCode errorCode = bp.DecodeBitUnsafe(out bit);
+ if (!bp.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
+
if (bit)
{
int stuff = (int)Block8x8F.GetScalarAt(b, 0);
@@ -558,8 +585,11 @@ namespace ImageSharp.Formats.Jpg
int z = 0;
int val;
- DecoderErrorCode errorCode = decoder.DecodeHuffmanUnsafe(ref h, out val);
- errorCode.EnsureNoEOF();
+ DecoderErrorCode errorCode = bp.DecodeHuffmanUnsafe(ref h, out val);
+ if (!bp.CheckEOF(errorCode))
+ {
+ return;
+ }
int val0 = val >> 4;
int val1 = val & 0x0f;
@@ -572,8 +602,11 @@ namespace ImageSharp.Formats.Jpg
this.eobRun = 1 << val0;
if (val0 != 0)
{
- errorCode = this.DecodeEobRun(val0, ref decoder);
- errorCode.EnsureNoError();
+ errorCode = this.DecodeEobRun(val0, ref bp);
+ if (!bp.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
}
done = true;
@@ -584,8 +617,11 @@ namespace ImageSharp.Formats.Jpg
z = delta;
bool bit;
- errorCode = decoder.DecodeBitUnsafe(out bit);
- errorCode.EnsureNoError();
+ errorCode = bp.DecodeBitUnsafe(out bit);
+ if (!bp.CheckEOFEnsureNoError(errorCode))
+ {
+ return;
+ }
if (!bit)
{
@@ -602,7 +638,12 @@ namespace ImageSharp.Formats.Jpg
break;
}
- zig = this.RefineNonZeroes(ref decoder, zig, val0, delta);
+ zig = this.RefineNonZeroes(ref bp, zig, val0, delta);
+ if (bp.UnexpectedEndOfStreamReached)
+ {
+ return;
+ }
+
if (zig > this.zigEnd)
{
throw new ImageFormatException($"Too many coefficients {zig} > {this.zigEnd}");
@@ -619,7 +660,7 @@ namespace ImageSharp.Formats.Jpg
if (this.eobRun > 0)
{
this.eobRun--;
- this.RefineNonZeroes(ref decoder, zig, -1, delta);
+ this.RefineNonZeroes(ref bp, zig, -1, delta);
}
}
@@ -627,12 +668,12 @@ namespace ImageSharp.Formats.Jpg
/// Refines non-zero entries of b in zig-zag order.
/// If >= 0, the first zero entries are skipped over.
///
- /// The decoder
+ /// The
/// The zig-zag start index
/// The non-zero entry
/// The low transform offset
/// The
- private int RefineNonZeroes(ref BufferProcessor decoder, int zig, int nz, int delta)
+ private int RefineNonZeroes(ref BufferProcessor bp, int zig, int nz, int delta)
{
var b = this.pointers.Block;
for (; zig <= this.zigEnd; zig++)
@@ -653,8 +694,11 @@ namespace ImageSharp.Formats.Jpg
}
bool bit;
- DecoderErrorCode errorCode = decoder.DecodeBitUnsafe(out bit);
- errorCode.EnsureNoError();
+ DecoderErrorCode errorCode = bp.DecodeBitUnsafe(out bit);
+ if (!bp.CheckEOFEnsureNoError(errorCode))
+ {
+ return int.MinValue;
+ }
if (!bit)
{
diff --git a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
index 6e2825447..cad81238c 100644
--- a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
@@ -397,9 +397,9 @@ namespace ImageSharp.Formats
// when this is a progressive image this gets called a number of times
// need to know how many times this should be called in total.
this.ProcessStartOfScan(remaining);
- if (!this.IsProgressive)
+ if (this.BufferProcessor.UnexpectedEndOfStreamReached || !this.IsProgressive)
{
- // if this is not a progressive image we can stop processing bytes as we now have the image data.
+ // if unexpeced EOF reached or this is not a progressive image we can stop processing bytes as we now have the image data.
processBytes = false;
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
index 3f8995088..bfe1f1e76 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
@@ -32,7 +32,7 @@ namespace ImageSharp.Tests
TestImages.Jpeg.Baseline.Jpeg444,
};
- [Theory] // Benchmark, enable manually
+ // [Theory] // Benchmark, enable manually
[MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg(string fileName)
{