Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct HuffmanTable
{
private bool isDerived;

private readonly MemoryAllocator memoryAllocator;

#pragma warning disable IDE0044 // Add readonly modifier
private fixed byte codeLengths[17];
#pragma warning restore IDE0044 // Add readonly modifier

/// <summary>
/// Gets the max code array
/// </summary>
Expand Down Expand Up @@ -50,16 +58,32 @@ internal unsafe struct HuffmanTable
/// <param name="values">The huffman values</param>
public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan<byte> codeLengths, ReadOnlySpan<byte> values)
{
this.isDerived = false;
this.memoryAllocator = memoryAllocator;
Unsafe.CopyBlockUnaligned(ref this.codeLengths[0], ref MemoryMarshal.GetReference(codeLengths), 17);
Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), 256);
}

/// <summary>
/// Expands the HuffmanTable into its derived form.
/// </summary>
/// <returns>The <see cref="HuffmanTable"/></returns>
public HuffmanTable Derive()
{
if (this.isDerived)
{
return this;
}

const int Length = 257;
using (IMemoryOwner<short> huffcode = memoryAllocator.Allocate<short>(Length))
using (IMemoryOwner<short> huffcode = this.memoryAllocator.Allocate<short>(Length))
{
ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan());
ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths);
ref byte codeLengthsRef = ref this.codeLengths[0];

// Figure C.1: make table of Huffman code length for each symbol
ref short sizesRef = ref this.Sizes[0];
short x = 0;

for (short i = 1; i < 17; i++)
{
byte length = Unsafe.Add(ref codeLengthsRef, i);
Expand Down Expand Up @@ -119,7 +143,8 @@ public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan<byte> codeLeng
}
}

Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), 256);
this.isDerived = true;
return this;
}
}
}
11 changes: 11 additions & 0 deletions src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ private void ParseBaselineDataInterleaved()

ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
dcHuffmanTable.Derive();
acHuffmanTable.Derive();

ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
Expand Down Expand Up @@ -234,6 +237,9 @@ private void ParseBaselineDataNonInterleaved()

ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
dcHuffmanTable.Derive();
acHuffmanTable.Derive();

ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);

int mcu = 0;
Expand Down Expand Up @@ -350,6 +356,8 @@ private void ParseProgressiveDataInterleaved()
int order = this.frame.ComponentOrder[k];
JpegComponent component = this.components[order];
ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
dcHuffmanTable.Derive();

int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;

Expand Down Expand Up @@ -405,6 +413,9 @@ private void ParseProgressiveDataNonInterleaved()

ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
dcHuffmanTable.Derive();
acHuffmanTable.Derive();

ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);

int mcu = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public partial class JpegDecoderTests
TestImages.Jpeg.Issues.Fuzz.ArgumentException826A,
TestImages.Jpeg.Issues.Fuzz.ArgumentException826B,
TestImages.Jpeg.Issues.Fuzz.ArgumentException826C,
TestImages.Jpeg.Issues.Fuzz.AccessViolationException827
TestImages.Jpeg.Issues.Fuzz.AccessViolationException827,
TestImages.Jpeg.Issues.Fuzz.ExecutionEngineException839
};

private static readonly Dictionary<string, float> CustomToleranceValues =
Expand Down
1 change: 1 addition & 0 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ public static class Fuzz
public const string ArgumentException826B = "Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg";
public const string ArgumentException826C = "Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg";
public const string AccessViolationException827 = "Jpg/issues/fuzz/Issue827-AccessViolationException.jpg";
public const string ExecutionEngineException839 = "Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg";
}
}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.