January 30, 2016

Recently I made a test to see the robustness of the Deflate algorithm in .NET Framework. It was written in Visual Studio 2013 using C# and DeflateStream class.

The test came back with one issue worth mentioning in this blog.

Background

IndexOutOfRangeException exception is thrown when the program tries to access out of the buffer boundaries. When this exception is thrown it indicates a missing or insufficient sanity check. When the sanity check works as expected it should prevent the exception from being thrown.

Microsoft explains like this.

Typically, an IndexOutOfRangeException exception is thrown as a result of developer error. Instead of handling the exception, you should diagnose the cause of the error and correct your code.

DeflateStream performs sanity check on the stream during the decompression and when a corrupted stream is detected InvalidDataException is being thrown.

The Issue

The issue the test hit is like this. During the decompression a specially crafted stream can bypass the sanity check and so the code doesn't throw InvalidDataException. Instead it tries to access out of boundaries and IndexOutOfRangeException is thrown.

c:\Dev\DeflateTestCase\bin\Release>DeflateTestCase.exeIndex was outside the bounds of the array. at System.IO.Compression.HuffmanTree.CreateTable() at System.IO.Compression.HuffmanTree..ctor(Byte[] codeLengths) at System.IO.Compression.Inflater.DecodeDynamicBlockHeader() at System.IO.Compression.Inflater.Decode() at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length) at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count) at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize) at System.IO.Stream.CopyTo(Stream destination) at DeflateTestCase.Program.Main(String[] args) in c:\Dev\DeflateTestCase\Program.cs:line 24

Consequence

If DeflateStream is used (either implicitly or expicitly) to decompress data and the data can come from untrusted source IndexOutOfRangeException is expected to happen and it should be handled in order to prevent the program from abrupt termination (DoS).