From 8b360d5fdaa2508dd37b1e0098ad16c9486c3617 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 2 Mar 2016 03:22:00 -0800 Subject: [PATCH] compress/bzip2: prevent zero-length Huffman codes Unlike RFC 1951 (DEFLATE), bzip2 does not use zero-length Huffman codes to indicate that the symbol is missing. Instead, bzip2 uses a sparse bitmap to indicate which symbols are present. Thus, it is undefined what happens when a length of zero is used. Thus, fix the parsing logic so that the length cannot ever go below 1-bit similar to how the C logic does things. To confirm that the C bzip2 utility chokes on this data: $ echo "425a6836314159265359b1f7404b000000400040002000217d184682ee48 a70a12163ee80960" | xxd -r -p | bzip2 -d bzip2: Data integrity error when decompressing For reference see: bzip2-1.0.6/decompress.c:320 Change-Id: Ic1568f8e7f80cdea51d887b4d712cc239c2fe85e Reviewed-on: https://go-review.googlesource.com/20119 Run-TryBot: Joe Tsai TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/compress/bzip2/bzip2.go | 6 +++--- src/compress/bzip2/bzip2_test.go | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/compress/bzip2/bzip2.go b/src/compress/bzip2/bzip2.go index b2063590c8..71e5372972 100644 --- a/src/compress/bzip2/bzip2.go +++ b/src/compress/bzip2/bzip2.go @@ -319,6 +319,9 @@ func (bz2 *reader) readBlock() (err error) { length := br.ReadBits(5) for j := range lengths { for { + if length < 1 || length > 20 { + return StructuralError("Huffman length out of range") + } if !br.ReadBit() { break } @@ -328,9 +331,6 @@ func (bz2 *reader) readBlock() (err error) { length++ } } - if length < 0 || length > 20 { - return StructuralError("Huffman length out of range") - } lengths[j] = uint8(length) } huffmanTrees[i], err = newHuffmanTree(lengths) diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go index 2acf40290c..82f1a42d83 100644 --- a/src/compress/bzip2/bzip2_test.go +++ b/src/compress/bzip2/bzip2_test.go @@ -172,6 +172,8 @@ const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c59 const badBlockSize = "425a683131415926535936dc55330063ffc0006000200020a40830008b0008b8bb9229c28481b6e2a998" +const badHuffmanDelta = "425a6836314159265359b1f7404b000000400040002000217d184682ee48a70a12163ee80960" + const ( digits = iota twain @@ -278,6 +280,13 @@ func TestBadBlockSize(t *testing.T) { } } +func TestBadHuffmanDelta(t *testing.T) { + _, err := decompressHex(badHuffmanDelta) + if err == nil { + t.Errorf("unexpected success") + } +} + var bufferOverrunBase64 string = ` QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3/// ////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD -- 2.48.1