Browse Source

Merge pull request #3080 from SixLabors/bp/fixIssue3078

Add check for span length in parse PNG pHYs chunk
pull/3089/head
James Jackson-South 7 months ago
committed by GitHub
parent
commit
65dd8bd587
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      src/ImageSharp/Formats/Png/Chunks/PngPhysical.cs
  2. 3
      src/ImageSharp/Formats/Png/PngThrowHelper.cs
  3. 17
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs

5
src/ImageSharp/Formats/Png/Chunks/PngPhysical.cs

@ -46,6 +46,11 @@ internal readonly struct PngPhysical
/// <returns>The parsed PhysicalChunkData.</returns> /// <returns>The parsed PhysicalChunkData.</returns>
public static PngPhysical Parse(ReadOnlySpan<byte> data) public static PngPhysical Parse(ReadOnlySpan<byte> data)
{ {
if (data.Length < 9)
{
PngThrowHelper.ThrowInvalidImageContentException("pHYs chunk is too short");
}
uint hResolution = BinaryPrimitives.ReadUInt32BigEndian(data[..4]); uint hResolution = BinaryPrimitives.ReadUInt32BigEndian(data[..4]);
uint vResolution = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(4, 4)); uint vResolution = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(4, 4));
byte unit = data[8]; byte unit = data[8];

3
src/ImageSharp/Formats/Png/PngThrowHelper.cs

@ -9,8 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Png;
internal static class PngThrowHelper internal static class PngThrowHelper
{ {
[DoesNotReturn] [DoesNotReturn]
public static void ThrowInvalidImageContentException(string errorMessage, Exception innerException) public static void ThrowInvalidImageContentException(string errorMessage) => throw new InvalidImageContentException(errorMessage);
=> throw new InvalidImageContentException(errorMessage, innerException);
[DoesNotReturn] [DoesNotReturn]
public static void ThrowInvalidHeader() => throw new InvalidImageContentException("PNG Image must contain a header chunk and it must be located before any other chunks."); public static void ThrowInvalidHeader() => throw new InvalidImageContentException("PNG Image must contain a header chunk and it must be located before any other chunks.");

17
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs

@ -70,13 +70,28 @@ public partial class PngDecoderTests
WriteChunk(memStream, chunkName); WriteChunk(memStream, chunkName);
WriteDataChunk(memStream); WriteDataChunk(memStream);
ImageFormatException exception = InvalidImageContentException exception =
Assert.Throws<InvalidImageContentException>(() => PngDecoder.Instance.Decode<Rgb24>(DecoderOptions.Default, memStream)); Assert.Throws<InvalidImageContentException>(() => PngDecoder.Instance.Decode<Rgb24>(DecoderOptions.Default, memStream));
Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message); Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message);
} }
} }
// https://github.com/SixLabors/ImageSharp/issues/3078
[Fact]
public void Decode_TruncatedPhysChunk_ExceptionIsThrown()
{
// 24 bytes — PNG signature + truncated pHYs chunk
byte[] payload = Convert.FromHexString(
"89504e470d0a1a0a3030303070485973" +
"3030303030303030");
using MemoryStream stream = new(payload);
InvalidImageContentException exception = Assert.Throws<InvalidImageContentException>(() => Image.Load<Rgba32>(stream));
Assert.Equal("pHYs chunk is too short", exception.Message);
}
private static string GetChunkTypeName(uint value) private static string GetChunkTypeName(uint value)
{ {
byte[] data = new byte[4]; byte[] data = new byte[4];

Loading…
Cancel
Save