Skip to content

Commit b99bf32

Browse files
Gracefully handle LZW overflows
1 parent b8d1cd8 commit b99bf32

File tree

5 files changed

+24
-2
lines changed

5 files changed

+24
-2
lines changed

src/ImageSharp/Formats/Gif/LzwDecoder.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public void DecodePixelRow(Span<byte> indices)
137137
ref int suffixRef = ref MemoryMarshal.GetReference(this.suffix.GetSpan());
138138
ref int pixelStackRef = ref MemoryMarshal.GetReference(this.pixelStack.GetSpan());
139139
Span<byte> buffer = this.scratchBuffer.GetSpan();
140+
int maxTop = this.pixelStack.Length() - 1;
140141

141142
int x = 0;
142143
int xyz = 0;
@@ -204,7 +205,7 @@ public void DecodePixelRow(Span<byte> indices)
204205
this.code = this.oldCode;
205206
}
206207

207-
while (this.code > this.clearCode)
208+
while (this.code > this.clearCode && this.top < maxTop)
208209
{
209210
Unsafe.Add(ref pixelStackRef, (uint)this.top++) = Unsafe.Add(ref suffixRef, (uint)this.code);
210211
this.code = Unsafe.Add(ref prefixRef, (uint)this.code);
@@ -250,6 +251,7 @@ public void SkipIndices(int length)
250251
ref int suffixRef = ref MemoryMarshal.GetReference(this.suffix.GetSpan());
251252
ref int pixelStackRef = ref MemoryMarshal.GetReference(this.pixelStack.GetSpan());
252253
Span<byte> buffer = this.scratchBuffer.GetSpan();
254+
int maxTop = this.pixelStack.Length() - 1;
253255

254256
int xyz = 0;
255257
while (xyz < length)
@@ -316,7 +318,7 @@ public void SkipIndices(int length)
316318
this.code = this.oldCode;
317319
}
318320

319-
while (this.code > this.clearCode)
321+
while (this.code > this.clearCode && this.top < maxTop)
320322
{
321323
Unsafe.Add(ref pixelStackRef, (uint)this.top++) = Unsafe.Add(ref suffixRef, (uint)this.code);
322324
this.code = Unsafe.Add(ref prefixRef, (uint)this.code);

tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

+12
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,16 @@ public void IssueTooLargeLzwBits<TPixel>(TestImageProvider<TPixel> provider)
334334
image.DebugSaveMultiFrame(provider);
335335
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact);
336336
}
337+
338+
// https://github.com/SixLabors/ImageSharp/issues/2859
339+
[Theory]
340+
[WithFile(TestImages.Gif.Issues.Issue2859_A, PixelTypes.Rgba32)]
341+
[WithFile(TestImages.Gif.Issues.Issue2859_B, PixelTypes.Rgba32)]
342+
public void Issue2859_LZWPixelStackOverflow<TPixel>(TestImageProvider<TPixel> provider)
343+
where TPixel : unmanaged, IPixel<TPixel>
344+
{
345+
using Image<TPixel> image = provider.GetImage();
346+
image.DebugSaveMultiFrame(provider);
347+
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact);
348+
}
337349
}

tests/ImageSharp.Tests/TestImages.cs

+2
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,8 @@ public static class Issues
535535
public const string Issue2450_B = "Gif/issues/issue_2450_2.gif";
536536
public const string Issue2198 = "Gif/issues/issue_2198.gif";
537537
public const string Issue2758 = "Gif/issues/issue_2758.gif";
538+
public const string Issue2859_A = "Gif/issues/issue_2859_A.gif";
539+
public const string Issue2859_B = "Gif/issues/issue_2859_B.gif";
538540
}
539541

540542
public static readonly string[] Animated =
Loading
Loading

0 commit comments

Comments
 (0)