-
-
Notifications
You must be signed in to change notification settings - Fork 851
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,11 @@ internal sealed class PngDecoderCore : IImageDecoderInternals | |
/// </summary> | ||
private readonly PngCrcChunkHandling pngCrcChunkHandling; | ||
|
||
/// <summary> | ||
/// The maximum memory in bytes that a zTXt, sPLT, iTXt, iCCP, or unknown chunk can occupy when decompressed. | ||
/// </summary> | ||
private readonly int maxUncompressedLength; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PngDecoderCore"/> class. | ||
/// </summary> | ||
|
@@ -132,6 +137,7 @@ public PngDecoderCore(PngDecoderOptions options) | |
this.skipMetadata = options.GeneralOptions.SkipMetadata; | ||
this.memoryAllocator = this.configuration.MemoryAllocator; | ||
this.pngCrcChunkHandling = options.PngCrcChunkHandling; | ||
this.maxUncompressedLength = options.MaxUncompressedAncillaryChunkSizeBytes; | ||
} | ||
|
||
internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly) | ||
|
@@ -143,6 +149,7 @@ internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly) | |
this.configuration = options.GeneralOptions.Configuration; | ||
this.memoryAllocator = this.configuration.MemoryAllocator; | ||
this.pngCrcChunkHandling = options.PngCrcChunkHandling; | ||
this.maxUncompressedLength = options.MaxUncompressedAncillaryChunkSizeBytes; | ||
} | ||
|
||
/// <inheritdoc/> | ||
|
@@ -596,23 +603,7 @@ private static void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan<byte> d | |
private void InitializeImage<TPixel>(ImageMetadata metadata, FrameControl frameControl, out Image<TPixel> image) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
JimBobSquarePants
Author
Member
|
||
where TPixel : unmanaged, IPixel<TPixel> | ||
{ | ||
// When ignoring data CRCs, we can't use the image constructor that leaves the buffer uncleared. | ||
if (this.pngCrcChunkHandling is PngCrcChunkHandling.IgnoreData or PngCrcChunkHandling.IgnoreAll) | ||
{ | ||
image = new Image<TPixel>( | ||
this.configuration, | ||
this.header.Width, | ||
this.header.Height, | ||
metadata); | ||
} | ||
else | ||
{ | ||
image = Image.CreateUninitialized<TPixel>( | ||
this.configuration, | ||
this.header.Width, | ||
this.header.Height, | ||
metadata); | ||
} | ||
image = new Image<TPixel>(this.configuration, this.header.Width, this.header.Height, metadata); | ||
|
||
PngFrameMetadata frameMetadata = image.Frames.RootFrame.Metadata.GetPngMetadata(); | ||
frameMetadata.FromChunk(in frameControl); | ||
|
@@ -1572,7 +1563,7 @@ private void ReadColorProfileChunk(ImageMetadata metadata, ReadOnlySpan<byte> da | |
|
||
ReadOnlySpan<byte> compressedData = data[(zeroIndex + 2)..]; | ||
|
||
if (this.TryDecompressZlibData(compressedData, out byte[] iccpProfileBytes)) | ||
if (this.TryDecompressZlibData(compressedData, this.maxUncompressedLength, out byte[] iccpProfileBytes)) | ||
{ | ||
metadata.IccProfile = new IccProfile(iccpProfileBytes); | ||
} | ||
|
@@ -1582,9 +1573,10 @@ private void ReadColorProfileChunk(ImageMetadata metadata, ReadOnlySpan<byte> da | |
/// Tries to decompress zlib compressed data. | ||
/// </summary> | ||
/// <param name="compressedData">The compressed data.</param> | ||
/// <param name="maxLength">The maximum uncompressed length.</param> | ||
/// <param name="uncompressedBytesArray">The uncompressed bytes array.</param> | ||
/// <returns>True, if de-compressing was successful.</returns> | ||
private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, out byte[] uncompressedBytesArray) | ||
private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, int maxLength, out byte[] uncompressedBytesArray) | ||
{ | ||
fixed (byte* compressedDataBase = compressedData) | ||
{ | ||
|
@@ -1604,6 +1596,12 @@ private unsafe bool TryDecompressZlibData(ReadOnlySpan<byte> compressedData, out | |
int bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); | ||
while (bytesRead != 0) | ||
{ | ||
if (memoryStreamOutput.Length > maxLength) | ||
{ | ||
uncompressedBytesArray = Array.Empty<byte>(); | ||
return false; | ||
} | ||
|
||
memoryStreamOutput.Write(destUncompressedData[..bytesRead]); | ||
bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); | ||
} | ||
|
@@ -1746,7 +1744,7 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan<byt | |
/// <returns>The <see cref="bool"/>.</returns> | ||
private bool TryDecompressTextData(ReadOnlySpan<byte> compressedData, Encoding encoding, [NotNullWhen(true)] out string? value) | ||
{ | ||
if (this.TryDecompressZlibData(compressedData, out byte[] uncompressedData)) | ||
if (this.TryDecompressZlibData(compressedData, this.maxUncompressedLength, out byte[] uncompressedData)) | ||
{ | ||
value = encoding.GetString(uncompressedData); | ||
return true; | ||
|
Is this going to be backported to the 2.x releases? I'm assuming this is the fix for CVE-2024-27929?