Skip to content

Commit 7e7c795

Browse files
Merge pull request #2690 from SixLabors/js/v3-updates
Merge 2681 to v4 Main
2 parents f44b761 + 8bf8698 commit 7e7c795

File tree

8 files changed

+64
-31
lines changed

8 files changed

+64
-31
lines changed

.github/workflows/build-and-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches:
66
- main
7+
- release/*
78
tags:
89
- "v*"
910
pull_request:

src/ImageSharp/Formats/Png/PngDecoderCore.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
126126
/// </summary>
127127
private readonly Crc32 crc32 = new();
128128

129+
/// <summary>
130+
/// The maximum memory in bytes that a zTXt, sPLT, iTXt, iCCP, or unknown chunk can occupy when decompressed.
131+
/// </summary>
132+
private readonly int maxUncompressedLength;
133+
129134
/// <summary>
130135
/// Initializes a new instance of the <see cref="PngDecoderCore"/> class.
131136
/// </summary>
@@ -138,6 +143,7 @@ public PngDecoderCore(PngDecoderOptions options)
138143
this.skipMetadata = options.GeneralOptions.SkipMetadata;
139144
this.memoryAllocator = this.configuration.MemoryAllocator;
140145
this.pngCrcChunkHandling = options.PngCrcChunkHandling;
146+
this.maxUncompressedLength = options.MaxUncompressedAncillaryChunkSizeBytes;
141147
}
142148

143149
internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly)
@@ -149,6 +155,7 @@ internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly)
149155
this.configuration = options.GeneralOptions.Configuration;
150156
this.memoryAllocator = this.configuration.MemoryAllocator;
151157
this.pngCrcChunkHandling = options.PngCrcChunkHandling;
158+
this.maxUncompressedLength = options.MaxUncompressedAncillaryChunkSizeBytes;
152159
}
153160

154161
/// <inheritdoc/>
@@ -602,23 +609,7 @@ private static void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan<byte> d
602609
private void InitializeImage<TPixel>(ImageMetadata metadata, FrameControl frameControl, out Image<TPixel> image)
603610
where TPixel : unmanaged, IPixel<TPixel>
604611
{
605-
// When ignoring data CRCs, we can't use the image constructor that leaves the buffer uncleared.
606-
if (this.pngCrcChunkHandling is PngCrcChunkHandling.IgnoreData or PngCrcChunkHandling.IgnoreAll)
607-
{
608-
image = new Image<TPixel>(
609-
this.configuration,
610-
this.header.Width,
611-
this.header.Height,
612-
metadata);
613-
}
614-
else
615-
{
616-
image = Image.CreateUninitialized<TPixel>(
617-
this.configuration,
618-
this.header.Width,
619-
this.header.Height,
620-
metadata);
621-
}
612+
image = new Image<TPixel>(this.configuration, this.header.Width, this.header.Height, metadata);
622613

623614
PngFrameMetadata frameMetadata = image.Frames.RootFrame.Metadata.GetPngMetadata();
624615
frameMetadata.FromChunk(in frameControl);
@@ -1575,7 +1566,7 @@ private void ReadColorProfileChunk(ImageMetadata metadata, ReadOnlySpan<byte> da
15751566

15761567
ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..];
15771568

1578-
if (this.TryDecompressZlibData(compressedData, out byte[] iccpProfileBytes))
1569+
if (this.TryDecompressZlibData(compressedData, this.maxUncompressedLength, out byte[] iccpProfileBytes))
15791570
{
15801571
metadata.IccProfile = new IccProfile(iccpProfileBytes);
15811572
}
@@ -1585,9 +1576,10 @@ private void ReadColorProfileChunk(ImageMetadata metadata, ReadOnlySpan<byte> da
15851576
/// Tries to decompress zlib compressed data.
15861577
/// </summary>
15871578
/// <param name="compressedData">The compressed data.</param>
1579+
/// <param name="maxLength">The maximum uncompressed length.</param>
15881580
/// <param name="uncompressedBytesArray">The uncompressed bytes array.</param>
15891581
/// <returns>True, if de-compressing was successful.</returns>
1590-
private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, out byte[] uncompressedBytesArray)
1582+
private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, int maxLength, out byte[] uncompressedBytesArray)
15911583
{
15921584
fixed (byte* compressedDataBase = compressedData)
15931585
{
@@ -1607,6 +1599,12 @@ private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, out
16071599
int bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length);
16081600
while (bytesRead != 0)
16091601
{
1602+
if (memoryStreamOutput.Length > maxLength)
1603+
{
1604+
uncompressedBytesArray = Array.Empty<byte>();
1605+
return false;
1606+
}
1607+
16101608
memoryStreamOutput.Write(destUncompressedData[..bytesRead]);
16111609
bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length);
16121610
}
@@ -1749,7 +1747,7 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan<byt
17491747
/// <returns>The <see cref="bool"/>.</returns>
17501748
private bool TryDecompressTextData(ReadOnlySpan<byte> compressedData, Encoding encoding, [NotNullWhen(true)] out string? value)
17511749
{
1752-
if (this.TryDecompressZlibData(compressedData, out byte[] uncompressedData))
1750+
if (this.TryDecompressZlibData(compressedData, this.maxUncompressedLength, out byte[] uncompressedData))
17531751
{
17541752
value = encoding.GetString(uncompressedData);
17551753
return true;

src/ImageSharp/Formats/Png/PngDecoderOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,10 @@ public sealed class PngDecoderOptions : ISpecializedDecoderOptions
1515
/// Gets a value indicating how to handle validation of any CRC (Cyclic Redundancy Check) data within the encoded PNG.
1616
/// </summary>
1717
public PngCrcChunkHandling PngCrcChunkHandling { get; init; } = PngCrcChunkHandling.IgnoreNonCritical;
18+
19+
/// <summary>
20+
/// Gets the maximum memory in bytes that a zTXt, sPLT, iTXt, iCCP, or unknown chunk can occupy when decompressed.
21+
/// Defaults to 8MB
22+
/// </summary>
23+
public int MaxUncompressedAncillaryChunkSizeBytes { get; init; } = 8 * 1024 * 1024; // 8MB
1824
}

src/ImageSharp/Formats/Webp/AlphaDecoder.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
88
using System.Runtime.Intrinsics;
9+
using System.Runtime.Intrinsics.Arm;
910
using System.Runtime.Intrinsics.X86;
11+
using SixLabors.ImageSharp.Common.Helpers;
1012
using SixLabors.ImageSharp.Formats.Webp.BitReader;
1113
using SixLabors.ImageSharp.Formats.Webp.Lossless;
1214
using SixLabors.ImageSharp.Memory;
@@ -311,8 +313,7 @@ private static void ColorIndexInverseTransformAlpha(
311313

312314
private static void HorizontalUnfilter(Span<byte> prev, Span<byte> input, Span<byte> dst, int width)
313315
{
314-
// TODO: Investigate AdvSimd support for this method.
315-
if (Sse2.IsSupported && width >= 9)
316+
if ((Sse2.IsSupported || AdvSimd.IsSupported) && width >= 9)
316317
{
317318
dst[0] = (byte)(input[0] + (prev.IsEmpty ? 0 : prev[0]));
318319
nuint i;
@@ -323,17 +324,17 @@ private static void HorizontalUnfilter(Span<byte> prev, Span<byte> input, Span<b
323324
for (i = 1; i <= (uint)width - 8; i += 8)
324325
{
325326
Vector128<long> a0 = Vector128.Create(Unsafe.As<byte, long>(ref Unsafe.Add(ref srcRef, i)), 0);
326-
Vector128<byte> a1 = Sse2.Add(a0.AsByte(), last.AsByte());
327-
Vector128<byte> a2 = Sse2.ShiftLeftLogical128BitLane(a1, 1);
328-
Vector128<byte> a3 = Sse2.Add(a1, a2);
329-
Vector128<byte> a4 = Sse2.ShiftLeftLogical128BitLane(a3, 2);
330-
Vector128<byte> a5 = Sse2.Add(a3, a4);
331-
Vector128<byte> a6 = Sse2.ShiftLeftLogical128BitLane(a5, 4);
332-
Vector128<byte> a7 = Sse2.Add(a5, a6);
327+
Vector128<byte> a1 = a0.AsByte() + last.AsByte();
328+
Vector128<byte> a2 = Vector128Utilities.ShiftLeftBytesInVector(a1, 1);
329+
Vector128<byte> a3 = a1 + a2;
330+
Vector128<byte> a4 = Vector128Utilities.ShiftLeftBytesInVector(a3, 2);
331+
Vector128<byte> a5 = a3 + a4;
332+
Vector128<byte> a6 = Vector128Utilities.ShiftLeftBytesInVector(a5, 4);
333+
Vector128<byte> a7 = a5 + a6;
333334

334335
ref byte outputRef = ref Unsafe.Add(ref dstRef, i);
335336
Unsafe.As<byte, Vector64<byte>>(ref outputRef) = a7.GetLower();
336-
last = Sse2.ShiftRightLogical(a7.AsInt64(), 56).AsInt32();
337+
last = Vector128.ShiftRightLogical(a7.AsInt64(), 56).AsInt32();
337338
}
338339

339340
for (; i < (uint)width; ++i)

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,4 +672,23 @@ public void Decode_Issue2666()
672672
string path = Path.GetFullPath(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Png.Issue2666));
673673
using Image image = Image.Load(path);
674674
}
675+
676+
[Theory]
677+
678+
[InlineData(TestImages.Png.Bad.BadZTXT)]
679+
[InlineData(TestImages.Png.Bad.BadZTXT2)]
680+
public void Decode_BadZTXT(string file)
681+
{
682+
string path = Path.GetFullPath(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, file));
683+
using Image image = Image.Load(path);
684+
}
685+
686+
[Theory]
687+
[InlineData(TestImages.Png.Bad.BadZTXT)]
688+
[InlineData(TestImages.Png.Bad.BadZTXT2)]
689+
public void Info_BadZTXT(string file)
690+
{
691+
string path = Path.GetFullPath(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, file));
692+
_ = Image.Identify(path);
693+
}
675694
}

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,10 @@ public static class Bad
186186
// Invalid color type.
187187
public const string ColorTypeOne = "Png/xc1n0g08.png";
188188
public const string ColorTypeNine = "Png/xc9n2c08.png";
189-
190189
public const string FlagOfGermany0000016446 = "Png/issues/flag_of_germany-0000016446.png";
190+
191+
public const string BadZTXT = "Png/issues/bad-ztxt.png";
192+
public const string BadZTXT2 = "Png/issues/bad-ztxt2.png";
191193
}
192194
}
193195

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)