Browse Source

Sampling factor validation

pull/1899/head
Dmitry Pentin 4 years ago
parent
commit
e045fbb023
  1. 11
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
  2. 29
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  3. 6
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs

11
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs

@ -19,21 +19,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.Frame = frame; this.Frame = frame;
this.Id = id; this.Id = id;
// Validate sampling factors.
if (horizontalFactor == 0 || verticalFactor == 0)
{
JpegThrowHelper.ThrowBadSampling();
}
this.HorizontalSamplingFactor = horizontalFactor; this.HorizontalSamplingFactor = horizontalFactor;
this.VerticalSamplingFactor = verticalFactor; this.VerticalSamplingFactor = verticalFactor;
this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor); this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor);
if (quantizationTableIndex > 3)
{
JpegThrowHelper.ThrowBadQuantizationTableIndex(quantizationTableIndex);
}
this.QuantizationTableIndex = quantizationTableIndex; this.QuantizationTableIndex = quantizationTableIndex;
this.Index = index; this.Index = index;
} }

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

@ -1022,10 +1022,26 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
int index = 0; int index = 0;
for (int i = 0; i < componentCount; i++) for (int i = 0; i < componentCount; i++)
{ {
// 1 byte: component identifier
byte componentId = this.temp[index];
// 1 byte: component sampling factors
byte hv = this.temp[index + 1]; byte hv = this.temp[index + 1];
int h = (hv >> 4) & 15; int h = (hv >> 4) & 15;
int v = hv & 15; int v = hv & 15;
// Validate: 1-4 range
if (h is < 1 or > 4)
{
JpegThrowHelper.ThrowInvalidImageContentException($"Bad horizontal sampling factor: {h}");
}
// Validate: 1-4 range
if (v is < 1 or > 4)
{
JpegThrowHelper.ThrowInvalidImageContentException($"Bad vertical sampling factor: {v}");
}
if (maxH < h) if (maxH < h)
{ {
maxH = h; maxH = h;
@ -1036,10 +1052,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
maxV = v; maxV = v;
} }
var component = new JpegComponent(this.Configuration.MemoryAllocator, this.Frame, this.temp[index], h, v, this.temp[index + 2], i); // 1 byte: quantization table destination selector
byte quantTableIndex = this.temp[index + 2];
// Validate: 0-3 range
if (quantTableIndex > 3)
{
JpegThrowHelper.ThrowBadQuantizationTableIndex(quantTableIndex);
}
var component = new JpegComponent(this.Configuration.MemoryAllocator, this.Frame, componentId, h, v, quantTableIndex, i);
this.Frame.Components[i] = component; this.Frame.Components[i] = component;
this.Frame.ComponentIds[i] = component.Id; this.Frame.ComponentIds[i] = componentId;
index += componentBytes; index += componentBytes;
} }

6
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs

@ -40,9 +40,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// LibJpeg can open this despite incorrect colorspace metadata. // LibJpeg can open this despite incorrect colorspace metadata.
TestImages.Jpeg.Issues.IncorrectColorspace855, TestImages.Jpeg.Issues.IncorrectColorspace855,
// LibJpeg can open this despite the invalid subsampling units.
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C,
// High depth images // High depth images
TestImages.Jpeg.Baseline.Testorig12bit, TestImages.Jpeg.Baseline.Testorig12bit,
}; };
@ -90,7 +87,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Issues.Fuzz.AccessViolationException827, TestImages.Jpeg.Issues.Fuzz.AccessViolationException827,
TestImages.Jpeg.Issues.Fuzz.ExecutionEngineException839, TestImages.Jpeg.Issues.Fuzz.ExecutionEngineException839,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException1693A, TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException1693A,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException1693B TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException1693B,
TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C,
}; };
private static readonly Dictionary<string, float> CustomToleranceValues = private static readonly Dictionary<string, float> CustomToleranceValues =

Loading…
Cancel
Save