BZip2InputStream: multiple crashes from malformed input

Open
#904 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
csharp
Domain
security

Research direction

Start in BZip2InputStream with RecvDecodingTables(), GetAndMoveToFrontDecode(), HbCreateDecodeTables(), and SetupBlock(), then run the five supplied malformed inputs to confirm each failure. Trace stream-derived values before array access and add regression coverage showing malformed data raises BZip2Exception or a similar decoder error rather than IndexOutOfRangeException or NullReferenceException.

Written by the indexing model from the issue text.

Description

bug bzip2
Describe the bug

Fuzzing SharpZipLib 1.4.2 with AFL++ and SharpFuzz found 5 unique crashes in BZip2InputStream, all triggered by small malformed .bz2 inputs (42–56 bytes). The BZip2 decoder does not validate header/block fields before using them as array indices, leading to IndexOutOfRangeException (4 crash sites) and NullReferenceException (1 crash site).

These are exploitable for denial of service — any application that decompresses user-supplied .bz2 data using SharpZipLib will crash on these inputs.

Crash 1 — IOOB in GetAndMoveToFrontDecode()
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.GetAndMoveToFrontDecode()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.InitBlock()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream..ctor(Stream stream)
Crash 2 — IOOB in HbCreateDecodeTables()
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.HbCreateDecodeTables(...)
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.RecvDecodingTables()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.GetAndMoveToFrontDecode()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.InitBlock()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream..ctor(Stream stream)
Crash 3 — IOOB in SetupBlock()
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.SetupBlock()
Crash 4 — IOOB in RecvDecodingTables()
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.RecvDecodingTables()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.GetAndMoveToFrontDecode()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.InitBlock()
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream..ctor(Stream stream)
Crash 5 — NullRef in SetupBlock()
System.NullReferenceException: Object reference not set to an instance of an object.
   at ICSharpCode.SharpZipLib.BZip2.BZip2InputStream.SetupBlock()
Reproduction Code

No response

Steps to reproduce
  1. Create a .NET console app and add SharpZipLib 1.4.2 NuGet package
  2. Paste the reproduction code
  3. Run the app
  4. Observe 4x IndexOutOfRangeException and 1x NullReferenceException
using ICSharpCode.SharpZipLib.BZip2;

// Crash 1 — IOOB in GetAndMoveToFrontDecode (56 bytes)
var crash1 = Convert.FromHexString("425a6839314159265359c1c08044a00030cd00c346299717724538e2000001410000100244a00030cd00c3462997177245385090c1c086e2");

// Crash 2 — IOOB in HbCreateDecodeTables (42 bytes)
var crash2 = Convert.FromHexString("425a6839314159265359c1c080e20003e8410000100244a000303200c3462997177245385090c1c080e2");

// Crash 3 — IOOB in SetupBlock (42 bytes)
var crash3 = Convert.FromHexString("425a6839314159265359c1c080e2a90001410000100244a00030cd00c3462997177245384290c1c080e2");

// Crash 4 — IOOB in RecvDecodingTables (42 bytes)
var crash4 = Convert.FromHexString("425a6839314159265359c1c080e2000001410000100244a000bfcd00c346299717724538500010c080e2");

// Crash 5 — NullRef in SetupBlock (42 bytes)
var crash5 = Convert.FromHexString("425a68c6314159265359c1c080e2000001410000100244a00030cd00c3672997177245385090c1c080e2");

foreach (var (name, data) in new[] { ("crash_1", crash1), ("crash_2", crash2), ("crash_3", crash3), ("crash_4", crash4), ("crash_5", crash5) })
{
    try
    {
        using var stream = new MemoryStream(data);
        using var bz2 = new BZip2InputStream(stream);
        var buffer = new byte[4096];
        while (bz2.Read(buffer, 0, buffer.Length) > 0) { }
        Console.WriteLine($"{name}: OK (no crash)");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"{name}: {ex.GetType().Name} — {ex.Message}");
    }
}
Expected behavior

BZip2InputStream should throw BZip2Exception (or similar) for malformed input, not crash with IndexOutOfRangeException or NullReferenceException. The BZip2 decoder should validate stream-derived values before using them as array indices.

Operating System

Linux

Framework Version

No response

Tags

BZip2

Additional context
  • Severity: Medium (denial of service)
  • Attack vector: Any application using BZip2InputStream to decompress untrusted input
  • Effect: Unhandled exception terminates the process
  • Workaround: Wrap BZip2InputStream usage in a try/catch for IndexOutOfRangeException and NullReferenceException
  • Suggested fix: Add bounds checks in RecvDecodingTables(), GetAndMoveToFrontDecode(), HbCreateDecodeTables(), and SetupBlock() before using stream-derived values as array indices. Malformed values should throw BZip2Exception (consistent with existing error handling in the decoder)
  • Found via coverage-guided fuzzing with AFL++ and SharpFuzz
Dominant language
C#
Stars
3.9k
Forks
1k
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from icsharpcode/SharpZipLib

All issues in icsharpcode/SharpZipLib

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.