From 2b52b55be6ca50a9f01d4689ebd9205eb49922de Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 5 Sep 2026 01:17:31 +1000 Subject: [PATCH] Validate WebP metadata chunk lengths --- .../Formats/Webp/WebpChunkParsingUtils.cs | 28 +++++++++++++------ .../Formats/WebP/WebpMetaDataTests.cs | 10 +++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs b/src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs index 119d53fe96..1e334057e7 100644 --- a/src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs +++ b/src/ImageSharp/Formats/Webp/WebpChunkParsingUtils.cs @@ -355,15 +355,15 @@ internal static class WebpChunkParsingUtils bool ignoreMetadata) { Span buffer = stackalloc byte[4]; - uint iccpChunkSize = ReadChunkSize(stream, buffer); + int iccpChunkSize = ValidateMetadataChunkSize(stream, ReadChunkSize(stream, buffer), "ICCP"); if (ignoreMetadata || metadata.IccProfile != null) { - stream.Skip((int)iccpChunkSize); + stream.Skip(iccpChunkSize); } else { byte[] iccpData = new byte[iccpChunkSize]; - int bytesRead = stream.Read(iccpData, 0, (int)iccpChunkSize); + int bytesRead = stream.Read(iccpData, 0, iccpChunkSize); if (bytesRead != iccpChunkSize) { WebpThrowHelper.ThrowInvalidImageContentException("Not enough data to read the iccp chunk"); @@ -391,15 +391,15 @@ internal static class WebpChunkParsingUtils bool ignoreMetadata) { Span buffer = stackalloc byte[4]; - uint exifChunkSize = ReadChunkSize(stream, buffer); + int exifChunkSize = ValidateMetadataChunkSize(stream, ReadChunkSize(stream, buffer), "EXIF"); if (ignoreMetadata || metadata.ExifProfile != null) { - stream.Skip((int)exifChunkSize); + stream.Skip(exifChunkSize); } else { byte[] exifData = new byte[exifChunkSize]; - int bytesRead = stream.Read(exifData, 0, (int)exifChunkSize); + int bytesRead = stream.Read(exifData, 0, exifChunkSize); if (bytesRead != exifChunkSize) { WebpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for the EXIF profile"); @@ -434,15 +434,15 @@ internal static class WebpChunkParsingUtils bool ignoreMetadata) { Span buffer = stackalloc byte[4]; - uint xmpChunkSize = ReadChunkSize(stream, buffer); + int xmpChunkSize = ValidateMetadataChunkSize(stream, ReadChunkSize(stream, buffer), "XMP"); if (ignoreMetadata || metadata.XmpProfile != null) { - stream.Skip((int)xmpChunkSize); + stream.Skip(xmpChunkSize); } else { byte[] xmpData = new byte[xmpChunkSize]; - int bytesRead = stream.Read(xmpData, 0, (int)xmpChunkSize); + int bytesRead = stream.Read(xmpData, 0, xmpChunkSize); if (bytesRead != xmpChunkSize) { WebpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for the XMP profile"); @@ -452,6 +452,16 @@ internal static class WebpChunkParsingUtils } } + private static int ValidateMetadataChunkSize(BufferedReadStream stream, uint chunkSize, string chunkName) + { + if (chunkSize > int.MaxValue || chunkSize > stream.Length - stream.Position) + { + WebpThrowHelper.ThrowInvalidImageContentException($"Not enough data to read the {chunkName} chunk"); + } + + return (int)chunkSize; + } + private static double GetExifResolutionValue(ExifProfile exifProfile, ExifTag tag) { if (exifProfile.TryGetValue(tag, out IExifValue? resolution)) diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs index 394479f89d..4092abfe69 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs @@ -228,4 +228,14 @@ public class WebpMetaDataTests using Image image = Image.Load(options, stream); }); } + + [Fact] + public void Decode_WithOversizedIccChunk_ThrowsInvalidImageContentException() + { + byte[] payload = Convert.FromHexString( + "524946462200000057454250565038580A0000002000000000000000000049434350FEFFFFFF01020304"); + + Assert.Throws(() => Image.Load(payload)); + Assert.Throws(() => Image.Identify(payload)); + } }