diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index 4d282f26c6..1a05178fdb 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -19,6 +19,11 @@ internal sealed class LzwDecoder : IDisposable
///
private const int MaxStackSize = 4096;
+ ///
+ /// The maximum bits for a lzw code.
+ ///
+ private const int MaximumLzwBits = 12;
+
///
/// The null code.
///
@@ -73,7 +78,7 @@ internal sealed class LzwDecoder : IDisposable
// It is possible to specify a larger LZW minimum code size than the palette length in bits
// which may leave a gap in the codes where no colors are assigned.
// http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp#lzw_compression
- if (minCodeSize < 2 || clearCode > MaxStackSize)
+ if (minCodeSize < 2 || minCodeSize > MaximumLzwBits || clearCode > MaxStackSize)
{
// Don't attempt to decode the frame indices.
// Theoretically we could determine a min code size from the length of the provided
@@ -245,7 +250,7 @@ internal sealed class LzwDecoder : IDisposable
// It is possible to specify a larger LZW minimum code size than the palette length in bits
// which may leave a gap in the codes where no colors are assigned.
// http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp#lzw_compression
- if (minCodeSize < 2 || clearCode > MaxStackSize)
+ if (minCodeSize < 2 || minCodeSize > MaximumLzwBits || clearCode > MaxStackSize)
{
// Don't attempt to decode the frame indices.
// Theoretically we could determine a min code size from the length of the provided
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
index 6399e1193e..7aabe03481 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
@@ -318,4 +318,21 @@ public class GifDecoderTests
image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
}
+
+ // https://github.com/SixLabors/ImageSharp/issues/2743
+ [Theory]
+ [WithFile(TestImages.Gif.Issues.BadMaxLzwBits, PixelTypes.Rgba32)]
+ public void IssueTooLargeLzwBits(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ Exception ex = Record.Exception(
+ () =>
+ {
+ using Image image = provider.GetImage();
+ image.DebugSave(provider);
+ });
+
+ Assert.NotNull(ex);
+ Assert.Contains("Gif Image does not contain a valid LZW minimum code.", ex.Message);
+ }
}
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index a45931e29e..7aaaac6f81 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -516,6 +516,7 @@ public static class TestImages
public const string BadAppExtLength = "Gif/issues/issue405_badappextlength252.gif";
public const string BadAppExtLength_2 = "Gif/issues/issue405_badappextlength252-2.gif";
public const string BadDescriptorWidth = "Gif/issues/issue403_baddescriptorwidth.gif";
+ public const string BadMaxLzwBits = "Gif/issues/issue_2743.gif";
public const string DeferredClearCode = "Gif/issues/bugzilla-55918.gif";
public const string Issue1505 = "Gif/issues/issue1505_argumentoutofrange.png";
public const string Issue1530 = "Gif/issues/issue1530.gif";
diff --git a/tests/Images/Input/Gif/issues/issue_2743.gif b/tests/Images/Input/Gif/issues/issue_2743.gif
new file mode 100644
index 0000000000..4ce61340d9
--- /dev/null
+++ b/tests/Images/Input/Gif/issues/issue_2743.gif
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4be51cb9c258a6518d791ad2810fa0d71449805a5d5a8f95dcc7da2dc558ed73
+size 166413