Browse Source

Merge branch 'main' into better_handle_corrupt_png

pull/2589/head
James Jackson-South 3 years ago
committed by GitHub
parent
commit
53dc3e3df6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  2. 6
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  3. 28
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  4. 11
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  5. 9
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  6. 6
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  7. 4
      tests/ImageSharp.Tests/TestImages.cs
  8. 3
      tests/Images/Input/Jpg/issues/issue-2564.jpg
  9. 3
      tests/Images/Input/Png/issues/flag_of_germany-0000016446.png
  10. 3
      tests/Images/Input/Tiff/Issues/Issue2587.tiff

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

@ -753,10 +753,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals
Span<byte> temp = stackalloc byte[2 * 16 * 4];
stream.Read(temp, 0, JFifMarker.Length);
if (!JFifMarker.TryParse(temp, out this.jFif))
{
JpegThrowHelper.ThrowNotSupportedException("Unknown App0 Marker - Expected JFIF.");
}
_ = JFifMarker.TryParse(temp, out this.jFif);
remaining -= JFifMarker.Length;

6
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -15,6 +15,7 @@ using SixLabors.ImageSharp.Formats.Png.Chunks;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Memory.Internals;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
@ -1873,6 +1874,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
[MethodImpl(InliningOptions.ShortMethod)]
private IMemoryOwner<byte> ReadChunkData(int length)
{
if (length == 0)
{
return new BasicArrayBuffer<byte>(Array.Empty<byte>());
}
// We rent the buffer here to return it afterwards in Decode()
IMemoryOwner<byte> buffer = this.configuration.MemoryAllocator.Allocate<byte>(length, AllocationOptions.Clean);

28
src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

@ -139,8 +139,8 @@ internal static class TiffDecoderOptionsParser
options.OldJpegCompressionStartOfImageMarker = jpegInterchangeFormatValue.Value;
}
options.ParseColorType(exifProfile);
options.ParseCompression(frameMetadata.Compression, exifProfile);
options.ParseColorType(exifProfile);
bool isTiled = VerifyRequiredFieldsArePresent(exifProfile, frameMetadata, options.PlanarConfiguration);
@ -194,7 +194,9 @@ internal static class TiffDecoderOptionsParser
}
}
if (frameMetadata.BitsPerPixel == null)
// For BiColor compressed images, the BitsPerPixel value will be set explicitly to 1, so we don't throw in those cases.
// See: https://github.com/SixLabors/ImageSharp/issues/2587
if (frameMetadata.BitsPerPixel == null && !IsBiColorCompression(frameMetadata.Compression))
{
TiffThrowHelper.ThrowNotSupported("The TIFF BitsPerSample entry is missing which is required to decode the image!");
}
@ -570,6 +572,11 @@ internal static class TiffDecoderOptionsParser
options.FaxCompressionOptions = FaxCompressionOptions.None;
}
// Some encoders do not set the BitsPerSample correctly, so we set those values here to the required values:
// https://github.com/SixLabors/ImageSharp/issues/2587
options.BitsPerSample = new TiffBitsPerSample(1, 0, 0);
options.BitsPerPixel = 1;
break;
}
@ -585,12 +592,18 @@ internal static class TiffDecoderOptionsParser
options.FaxCompressionOptions = FaxCompressionOptions.None;
}
options.BitsPerSample = new TiffBitsPerSample(1, 0, 0);
options.BitsPerPixel = 1;
break;
}
case TiffCompression.Ccitt1D:
{
options.CompressionType = TiffDecoderCompressionType.HuffmanRle;
options.BitsPerSample = new TiffBitsPerSample(1, 0, 0);
options.BitsPerPixel = 1;
break;
}
@ -645,4 +658,15 @@ internal static class TiffDecoderOptionsParser
}
}
}
private static bool IsBiColorCompression(TiffCompression? compression)
{
if (compression is TiffCompression.Ccitt1D or TiffCompression.CcittGroup3Fax or
TiffCompression.CcittGroup4Fax)
{
return true;
}
return false;
}
}

11
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -326,6 +326,17 @@ public partial class JpegDecoderTests
image.CompareToOriginal(provider);
}
// https://github.com/SixLabors/ImageSharp/discussions/2564
[Theory]
[WithFile(TestImages.Jpeg.Issues.Issue2564, PixelTypes.Rgba32)]
public void Issue2564_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
[Theory]
[WithFile(TestImages.Jpeg.Issues.HangBadScan, PixelTypes.L8)]
public void DecodeHang<TPixel>(TestImageProvider<TPixel> provider)

9
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -647,4 +647,13 @@ public partial class PngDecoderTests
"Disco")
.Dispose();
}
[Fact]
public void Binary_PrematureEof()
{
using EofHitCounter eofHitCounter = EofHitCounter.RunDecoder(TestImages.Png.Bad.FlagOfGermany0000016446);
Assert.True(eofHitCounter.EofHitCount <= 2);
Assert.Equal(new Size(200, 120), eofHitCounter.Image.Size);
}
}

6
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -665,6 +665,12 @@ public class TiffDecoderTests : TiffDecoderBaseTester
public void TiffDecoder_CanDecode_TiledWithNonEqualWidthAndHeight<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
// https://github.com/SixLabors/ImageSharp/issues/2587
[Theory]
[WithFile(Issues2587, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_BiColorWithMissingBitsPerSample<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(JpegCompressedGray0000539558, PixelTypes.Rgba32)]
public void TiffDecoder_ThrowsException_WithCircular_IFD_Offsets<TPixel>(TestImageProvider<TPixel> provider)

4
tests/ImageSharp.Tests/TestImages.cs

@ -180,6 +180,8 @@ public static class TestImages
// Invalid color type.
public const string ColorTypeOne = "Png/xc1n0g08.png";
public const string ColorTypeNine = "Png/xc9n2c08.png";
public const string FlagOfGermany0000016446 = "Png/issues/flag_of_germany-0000016446.png";
}
}
@ -302,6 +304,7 @@ public static class TestImages
public const string Issue2334_NotEnoughBytesA = "Jpg/issues/issue-2334-a.jpg";
public const string Issue2334_NotEnoughBytesB = "Jpg/issues/issue-2334-b.jpg";
public const string Issue2478_JFXX = "Jpg/issues/issue-2478-jfxx.jpg";
public const string Issue2564 = "Jpg/issues/issue-2564.jpg";
public const string HangBadScan = "Jpg/issues/Hang_C438A851.jpg";
public static class Fuzz
@ -992,6 +995,7 @@ public static class TestImages
public const string Issues2149 = "Tiff/Issues/Group4CompressionWithStrips.tiff";
public const string Issues2255 = "Tiff/Issues/Issue2255.png";
public const string Issues2435 = "Tiff/Issues/Issue2435.tiff";
public const string Issues2587 = "Tiff/Issues/Issue2587.tiff";
public const string JpegCompressedGray0000539558 = "Tiff/Issues/JpegCompressedGray-0000539558.tiff";
public const string Tiled0000023664 = "Tiff/Issues/tiled-0000023664.tiff";

3
tests/Images/Input/Jpg/issues/issue-2564.jpg

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:08f215c777b6fe8e315f18b7f93611c90fa86fefb8e3d37181890afb3068d8bd
size 939150

3
tests/Images/Input/Png/issues/flag_of_germany-0000016446.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64633823874512ff9f37bd321184d548816e97b8898622ae7d912b59f3099a35
size 16446

3
tests/Images/Input/Tiff/Issues/Issue2587.tiff

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b5a245e4313bcf942d9a8ab7108946ddcadcf45d898b8a8986fc42a6e8c64dc2
size 87746
Loading…
Cancel
Save