Source file src/compress/gzip/gunzip_test.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gzip
     6  
     7  import (
     8  	"bytes"
     9  	"compress/flate"
    10  	"encoding/base64"
    11  	"io"
    12  	"os"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  )
    17  
    18  type gunzipTest struct {
    19  	name string
    20  	desc string
    21  	raw  string
    22  	gzip []byte
    23  	err  error
    24  }
    25  
    26  var gunzipTests = []gunzipTest{
    27  	{ // has 1 empty fixed-huffman block
    28  		"empty.txt",
    29  		"empty.txt",
    30  		"",
    31  		[]byte{
    32  			0x1f, 0x8b, 0x08, 0x08, 0xf7, 0x5e, 0x14, 0x4a,
    33  			0x00, 0x03, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
    34  			0x74, 0x78, 0x74, 0x00, 0x03, 0x00, 0x00, 0x00,
    35  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    36  		},
    37  		nil,
    38  	},
    39  	{
    40  		"",
    41  		"empty - with no file name",
    42  		"",
    43  		[]byte{
    44  			0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88,
    45  			0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00,
    46  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    47  		},
    48  		nil,
    49  	},
    50  	{ // has 1 non-empty fixed huffman block
    51  		"hello.txt",
    52  		"hello.txt",
    53  		"hello world\n",
    54  		[]byte{
    55  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
    56  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
    57  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
    58  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
    59  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
    60  			0x00, 0x00,
    61  		},
    62  		nil,
    63  	},
    64  	{ // concatenation
    65  		"hello.txt",
    66  		"hello.txt x2",
    67  		"hello world\n" +
    68  			"hello world\n",
    69  		[]byte{
    70  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
    71  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
    72  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
    73  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
    74  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
    75  			0x00, 0x00,
    76  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
    77  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
    78  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
    79  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
    80  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
    81  			0x00, 0x00,
    82  		},
    83  		nil,
    84  	},
    85  	{ // has a fixed huffman block with some length-distance pairs
    86  		"shesells.txt",
    87  		"shesells.txt",
    88  		"she sells seashells by the seashore\n",
    89  		[]byte{
    90  			0x1f, 0x8b, 0x08, 0x08, 0x72, 0x66, 0x8b, 0x4a,
    91  			0x00, 0x03, 0x73, 0x68, 0x65, 0x73, 0x65, 0x6c,
    92  			0x6c, 0x73, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x2b,
    93  			0xce, 0x48, 0x55, 0x28, 0x4e, 0xcd, 0xc9, 0x29,
    94  			0x06, 0x92, 0x89, 0xc5, 0x19, 0x60, 0x56, 0x52,
    95  			0xa5, 0x42, 0x09, 0x58, 0x18, 0x28, 0x90, 0x5f,
    96  			0x94, 0xca, 0x05, 0x00, 0x76, 0xb0, 0x3b, 0xeb,
    97  			0x24, 0x00, 0x00, 0x00,
    98  		},
    99  		nil,
   100  	},
   101  	{ // has dynamic huffman blocks
   102  		"gettysburg",
   103  		"gettysburg",
   104  		"  Four score and seven years ago our fathers brought forth on\n" +
   105  			"this continent, a new nation, conceived in Liberty, and dedicated\n" +
   106  			"to the proposition that all men are created equal.\n" +
   107  			"  Now we are engaged in a great Civil War, testing whether that\n" +
   108  			"nation, or any nation so conceived and so dedicated, can long\n" +
   109  			"endure.\n" +
   110  			"  We are met on a great battle-field of that war.\n" +
   111  			"  We have come to dedicate a portion of that field, as a final\n" +
   112  			"resting place for those who here gave their lives that that\n" +
   113  			"nation might live.  It is altogether fitting and proper that\n" +
   114  			"we should do this.\n" +
   115  			"  But, in a larger sense, we can not dedicate — we can not\n" +
   116  			"consecrate — we can not hallow — this ground.\n" +
   117  			"  The brave men, living and dead, who struggled here, have\n" +
   118  			"consecrated it, far above our poor power to add or detract.\n" +
   119  			"The world will little note, nor long remember what we say here,\n" +
   120  			"but it can never forget what they did here.\n" +
   121  			"  It is for us the living, rather, to be dedicated here to the\n" +
   122  			"unfinished work which they who fought here have thus far so\n" +
   123  			"nobly advanced.  It is rather for us to be here dedicated to\n" +
   124  			"the great task remaining before us — that from these honored\n" +
   125  			"dead we take increased devotion to that cause for which they\n" +
   126  			"gave the last full measure of devotion —\n" +
   127  			"  that we here highly resolve that these dead shall not have\n" +
   128  			"died in vain — that this nation, under God, shall have a new\n" +
   129  			"birth of freedom — and that government of the people, by the\n" +
   130  			"people, for the people, shall not perish from this earth.\n" +
   131  			"\n" +
   132  			"Abraham Lincoln, November 19, 1863, Gettysburg, Pennsylvania\n",
   133  		[]byte{
   134  			0x1f, 0x8b, 0x08, 0x08, 0xd1, 0x12, 0x2b, 0x4a,
   135  			0x00, 0x03, 0x67, 0x65, 0x74, 0x74, 0x79, 0x73,
   136  			0x62, 0x75, 0x72, 0x67, 0x00, 0x65, 0x54, 0xcd,
   137  			0x6e, 0xd4, 0x30, 0x10, 0xbe, 0xfb, 0x29, 0xe6,
   138  			0x01, 0x42, 0xa5, 0x0a, 0x09, 0xc1, 0x11, 0x90,
   139  			0x40, 0x48, 0xa8, 0xe2, 0x80, 0xd4, 0xf3, 0x24,
   140  			0x9e, 0x24, 0x56, 0xbd, 0x9e, 0xc5, 0x76, 0x76,
   141  			0x95, 0x1b, 0x0f, 0xc1, 0x13, 0xf2, 0x24, 0x7c,
   142  			0x63, 0x77, 0x9b, 0x4a, 0x5c, 0xaa, 0x6e, 0x6c,
   143  			0xcf, 0x7c, 0x7f, 0x33, 0x44, 0x5f, 0x74, 0xcb,
   144  			0x54, 0x26, 0xcd, 0x42, 0x9c, 0x3c, 0x15, 0xb9,
   145  			0x48, 0xa2, 0x5d, 0x38, 0x17, 0xe2, 0x45, 0xc9,
   146  			0x4e, 0x67, 0xae, 0xab, 0xe0, 0xf7, 0x98, 0x75,
   147  			0x5b, 0xd6, 0x4a, 0xb3, 0xe6, 0xba, 0x92, 0x26,
   148  			0x57, 0xd7, 0x50, 0x68, 0xd2, 0x54, 0x43, 0x92,
   149  			0x54, 0x07, 0x62, 0x4a, 0x72, 0xa5, 0xc4, 0x35,
   150  			0x68, 0x1a, 0xec, 0x60, 0x92, 0x70, 0x11, 0x4f,
   151  			0x21, 0xd1, 0xf7, 0x30, 0x4a, 0xae, 0xfb, 0xd0,
   152  			0x9a, 0x78, 0xf1, 0x61, 0xe2, 0x2a, 0xde, 0x55,
   153  			0x25, 0xd4, 0xa6, 0x73, 0xd6, 0xb3, 0x96, 0x60,
   154  			0xef, 0xf0, 0x9b, 0x2b, 0x71, 0x8c, 0x74, 0x02,
   155  			0x10, 0x06, 0xac, 0x29, 0x8b, 0xdd, 0x25, 0xf9,
   156  			0xb5, 0x71, 0xbc, 0x73, 0x44, 0x0f, 0x7a, 0xa5,
   157  			0xab, 0xb4, 0x33, 0x49, 0x0b, 0x2f, 0xbd, 0x03,
   158  			0xd3, 0x62, 0x17, 0xe9, 0x73, 0xb8, 0x84, 0x48,
   159  			0x8f, 0x9c, 0x07, 0xaa, 0x52, 0x00, 0x6d, 0xa1,
   160  			0xeb, 0x2a, 0xc6, 0xa0, 0x95, 0x76, 0x37, 0x78,
   161  			0x9a, 0x81, 0x65, 0x7f, 0x46, 0x4b, 0x45, 0x5f,
   162  			0xe1, 0x6d, 0x42, 0xe8, 0x01, 0x13, 0x5c, 0x38,
   163  			0x51, 0xd4, 0xb4, 0x38, 0x49, 0x7e, 0xcb, 0x62,
   164  			0x28, 0x1e, 0x3b, 0x82, 0x93, 0x54, 0x48, 0xf1,
   165  			0xd2, 0x7d, 0xe4, 0x5a, 0xa3, 0xbc, 0x99, 0x83,
   166  			0x44, 0x4f, 0x3a, 0x77, 0x36, 0x57, 0xce, 0xcf,
   167  			0x2f, 0x56, 0xbe, 0x80, 0x90, 0x9e, 0x84, 0xea,
   168  			0x51, 0x1f, 0x8f, 0xcf, 0x90, 0xd4, 0x60, 0xdc,
   169  			0x5e, 0xb4, 0xf7, 0x10, 0x0b, 0x26, 0xe0, 0xff,
   170  			0xc4, 0xd1, 0xe5, 0x67, 0x2e, 0xe7, 0xc8, 0x93,
   171  			0x98, 0x05, 0xb8, 0xa8, 0x45, 0xc0, 0x4d, 0x09,
   172  			0xdc, 0x84, 0x16, 0x2b, 0x0d, 0x9a, 0x21, 0x53,
   173  			0x04, 0x8b, 0xd2, 0x0b, 0xbd, 0xa2, 0x4c, 0xa7,
   174  			0x60, 0xee, 0xd9, 0xe1, 0x1d, 0xd1, 0xb7, 0x4a,
   175  			0x30, 0x8f, 0x63, 0xd5, 0xa5, 0x8b, 0x33, 0x87,
   176  			0xda, 0x1a, 0x18, 0x79, 0xf3, 0xe3, 0xa6, 0x17,
   177  			0x94, 0x2e, 0xab, 0x6e, 0xa0, 0xe3, 0xcd, 0xac,
   178  			0x50, 0x8c, 0xca, 0xa7, 0x0d, 0x76, 0x37, 0xd1,
   179  			0x23, 0xe7, 0x05, 0x57, 0x8b, 0xa4, 0x22, 0x83,
   180  			0xd9, 0x62, 0x52, 0x25, 0xad, 0x07, 0xbb, 0xbf,
   181  			0xbf, 0xff, 0xbc, 0xfa, 0xee, 0x20, 0x73, 0x91,
   182  			0x29, 0xff, 0x7f, 0x02, 0x71, 0x62, 0x84, 0xb5,
   183  			0xf6, 0xb5, 0x25, 0x6b, 0x41, 0xde, 0x92, 0xb7,
   184  			0x76, 0x3f, 0x91, 0x91, 0x31, 0x1b, 0x41, 0x84,
   185  			0x62, 0x30, 0x0a, 0x37, 0xa4, 0x5e, 0x18, 0x3a,
   186  			0x99, 0x08, 0xa5, 0xe6, 0x6d, 0x59, 0x22, 0xec,
   187  			0x33, 0x39, 0x86, 0x26, 0xf5, 0xab, 0x66, 0xc8,
   188  			0x08, 0x20, 0xcf, 0x0c, 0xd7, 0x47, 0x45, 0x21,
   189  			0x0b, 0xf6, 0x59, 0xd5, 0xfe, 0x5c, 0x8d, 0xaa,
   190  			0x12, 0x7b, 0x6f, 0xa1, 0xf0, 0x52, 0x33, 0x4f,
   191  			0xf5, 0xce, 0x59, 0xd3, 0xab, 0x66, 0x10, 0xbf,
   192  			0x06, 0xc4, 0x31, 0x06, 0x73, 0xd6, 0x80, 0xa2,
   193  			0x78, 0xc2, 0x45, 0xcb, 0x03, 0x65, 0x39, 0xc9,
   194  			0x09, 0xd1, 0x06, 0x04, 0x33, 0x1a, 0x5a, 0xf1,
   195  			0xde, 0x01, 0xb8, 0x71, 0x83, 0xc4, 0xb5, 0xb3,
   196  			0xc3, 0x54, 0x65, 0x33, 0x0d, 0x5a, 0xf7, 0x9b,
   197  			0x90, 0x7c, 0x27, 0x1f, 0x3a, 0x58, 0xa3, 0xd8,
   198  			0xfd, 0x30, 0x5f, 0xb7, 0xd2, 0x66, 0xa2, 0x93,
   199  			0x1c, 0x28, 0xb7, 0xe9, 0x1b, 0x0c, 0xe1, 0x28,
   200  			0x47, 0x26, 0xbb, 0xe9, 0x7d, 0x7e, 0xdc, 0x96,
   201  			0x10, 0x92, 0x50, 0x56, 0x7c, 0x06, 0xe2, 0x27,
   202  			0xb4, 0x08, 0xd3, 0xda, 0x7b, 0x98, 0x34, 0x73,
   203  			0x9f, 0xdb, 0xf6, 0x62, 0xed, 0x31, 0x41, 0x13,
   204  			0xd3, 0xa2, 0xa8, 0x4b, 0x3a, 0xc6, 0x1d, 0xe4,
   205  			0x2f, 0x8c, 0xf8, 0xfb, 0x97, 0x64, 0xf4, 0xb6,
   206  			0x2f, 0x80, 0x5a, 0xf3, 0x56, 0xe0, 0x40, 0x50,
   207  			0xd5, 0x19, 0xd0, 0x1e, 0xfc, 0xca, 0xe5, 0xc9,
   208  			0xd4, 0x60, 0x00, 0x81, 0x2e, 0xa3, 0xcc, 0xb6,
   209  			0x52, 0xf0, 0xb4, 0xdb, 0x69, 0x99, 0xce, 0x7a,
   210  			0x32, 0x4c, 0x08, 0xed, 0xaa, 0x10, 0x10, 0xe3,
   211  			0x6f, 0xee, 0x99, 0x68, 0x95, 0x9f, 0x04, 0x71,
   212  			0xb2, 0x49, 0x2f, 0x62, 0xa6, 0x5e, 0xb4, 0xef,
   213  			0x02, 0xed, 0x4f, 0x27, 0xde, 0x4a, 0x0f, 0xfd,
   214  			0xc1, 0xcc, 0xdd, 0x02, 0x8f, 0x08, 0x16, 0x54,
   215  			0xdf, 0xda, 0xca, 0xe0, 0x82, 0xf1, 0xb4, 0x31,
   216  			0x7a, 0xa9, 0x81, 0xfe, 0x90, 0xb7, 0x3e, 0xdb,
   217  			0xd3, 0x35, 0xc0, 0x20, 0x80, 0x33, 0x46, 0x4a,
   218  			0x63, 0xab, 0xd1, 0x0d, 0x29, 0xd2, 0xe2, 0x84,
   219  			0xb8, 0xdb, 0xfa, 0xe9, 0x89, 0x44, 0x86, 0x7c,
   220  			0xe8, 0x0b, 0xe6, 0x02, 0x6a, 0x07, 0x9b, 0x96,
   221  			0xd0, 0xdb, 0x2e, 0x41, 0x4c, 0xa1, 0xd5, 0x57,
   222  			0x45, 0x14, 0xfb, 0xe3, 0xa6, 0x72, 0x5b, 0x87,
   223  			0x6e, 0x0c, 0x6d, 0x5b, 0xce, 0xe0, 0x2f, 0xe2,
   224  			0x21, 0x81, 0x95, 0xb0, 0xe8, 0xb6, 0x32, 0x0b,
   225  			0xb2, 0x98, 0x13, 0x52, 0x5d, 0xfb, 0xec, 0x63,
   226  			0x17, 0x8a, 0x9e, 0x23, 0x22, 0x36, 0xee, 0xcd,
   227  			0xda, 0xdb, 0xcf, 0x3e, 0xf1, 0xc7, 0xf1, 0x01,
   228  			0x12, 0x93, 0x0a, 0xeb, 0x6f, 0xf2, 0x02, 0x15,
   229  			0x96, 0x77, 0x5d, 0xef, 0x9c, 0xfb, 0x88, 0x91,
   230  			0x59, 0xf9, 0x84, 0xdd, 0x9b, 0x26, 0x8d, 0x80,
   231  			0xf9, 0x80, 0x66, 0x2d, 0xac, 0xf7, 0x1f, 0x06,
   232  			0xba, 0x7f, 0xff, 0xee, 0xed, 0x40, 0x5f, 0xa5,
   233  			0xd6, 0xbd, 0x8c, 0x5b, 0x46, 0xd2, 0x7e, 0x48,
   234  			0x4a, 0x65, 0x8f, 0x08, 0x42, 0x60, 0xf7, 0x0f,
   235  			0xb9, 0x16, 0x0b, 0x0c, 0x1a, 0x06, 0x00, 0x00,
   236  		},
   237  		nil,
   238  	},
   239  	{ // has 1 non-empty fixed huffman block then garbage
   240  		"hello.txt",
   241  		"hello.txt + garbage",
   242  		"hello world\n",
   243  		[]byte{
   244  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
   245  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   246  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   247  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   248  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
   249  			0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
   250  		},
   251  		ErrHeader,
   252  	},
   253  	{ // has 1 non-empty fixed huffman block not enough header
   254  		"hello.txt",
   255  		"hello.txt + garbage",
   256  		"hello world\n",
   257  		[]byte{
   258  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
   259  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   260  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   261  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   262  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
   263  			0x00, 0x00, gzipID1,
   264  		},
   265  		io.ErrUnexpectedEOF,
   266  	},
   267  	{ // has 1 non-empty fixed huffman block but corrupt checksum
   268  		"hello.txt",
   269  		"hello.txt + corrupt checksum",
   270  		"hello world\n",
   271  		[]byte{
   272  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
   273  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   274  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   275  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   276  			0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00,
   277  			0x00, 0x00,
   278  		},
   279  		ErrChecksum,
   280  	},
   281  	{ // has 1 non-empty fixed huffman block but corrupt size
   282  		"hello.txt",
   283  		"hello.txt + corrupt size",
   284  		"hello world\n",
   285  		[]byte{
   286  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
   287  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   288  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   289  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   290  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0xff, 0x00,
   291  			0x00, 0x00,
   292  		},
   293  		ErrChecksum,
   294  	},
   295  	{
   296  		"f1l3n4m3.tXt",
   297  		"header with all fields used",
   298  		"",
   299  		[]byte{
   300  			0x1f, 0x8b, 0x08, 0x1e, 0x70, 0xf0, 0xf9, 0x4a,
   301  			0x00, 0xaa, 0x09, 0x00, 0x7a, 0x7a, 0x05, 0x00,
   302  			0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x31, 0x6c,
   303  			0x33, 0x6e, 0x34, 0x6d, 0x33, 0x2e, 0x74, 0x58,
   304  			0x74, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
   305  			0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
   306  			0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
   307  			0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
   308  			0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
   309  			0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
   310  			0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
   311  			0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
   312  			0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
   313  			0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
   314  			0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
   315  			0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
   316  			0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
   317  			0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
   318  			0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
   319  			0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e,
   320  			0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
   321  			0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
   322  			0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
   323  			0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
   324  			0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
   325  			0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
   326  			0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
   327  			0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe,
   328  			0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
   329  			0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
   330  			0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
   331  			0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
   332  			0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
   333  			0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
   334  			0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
   335  			0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
   336  			0xff, 0x00, 0x92, 0xfd, 0x01, 0x00, 0x00, 0xff,
   337  			0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   338  			0x00,
   339  		},
   340  		nil,
   341  	},
   342  	{
   343  		"",
   344  		"truncated gzip file amid raw-block",
   345  		"hello",
   346  		[]byte{
   347  			0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
   348  			0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
   349  		},
   350  		io.ErrUnexpectedEOF,
   351  	},
   352  	{
   353  		"",
   354  		"truncated gzip file amid fixed-block",
   355  		"He",
   356  		[]byte{
   357  			0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
   358  			0xf2, 0x48, 0xcd,
   359  		},
   360  		io.ErrUnexpectedEOF,
   361  	},
   362  	{
   363  		"hello.txt",
   364  		"gzip header with truncated name",
   365  		"hello world\n",
   366  		[]byte{
   367  			0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x58, 0x13, 0x4a,
   368  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   369  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   370  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   371  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
   372  			0x00, 0x00,
   373  			0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
   374  			0x00, 0xff, 0x01,
   375  		},
   376  		io.ErrUnexpectedEOF,
   377  	},
   378  	{
   379  		"",
   380  		"gzip header with truncated comment",
   381  		"hello world\n",
   382  		[]byte{
   383  			0x1f, 0x8b, 0x08, 0x10, 0xc8, 0x58, 0x13, 0x4a,
   384  			0x00, 0x03, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e,
   385  			0x74, 0x78, 0x74, 0x00, 0xcb, 0x48, 0xcd, 0xc9,
   386  			0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1,
   387  			0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
   388  			0x00, 0x00,
   389  			0x1f, 0x8b, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00,
   390  			0x00, 0xff, 0x01,
   391  		},
   392  		io.ErrUnexpectedEOF,
   393  	},
   394  }
   395  
   396  func TestDecompressor(t *testing.T) {
   397  	// Keep resetting this reader.
   398  	// It is intended behavior that Reader.Reset can be called on a zero-value
   399  	// Reader and be the equivalent as if NewReader was used instead.
   400  	r1 := new(Reader)
   401  
   402  	b := new(bytes.Buffer)
   403  	for _, tt := range gunzipTests {
   404  		// Test NewReader.
   405  		in := bytes.NewReader(tt.gzip)
   406  		r2, err := NewReader(in)
   407  		if err != nil {
   408  			t.Errorf("%s: NewReader: %s", tt.desc, err)
   409  			continue
   410  		}
   411  		defer r2.Close()
   412  		if tt.name != r2.Name {
   413  			t.Errorf("%s: got name %s", tt.desc, r2.Name)
   414  		}
   415  		b.Reset()
   416  		n, err := io.Copy(b, r2)
   417  		if err != tt.err {
   418  			t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
   419  		}
   420  		s := b.String()
   421  		if s != tt.raw {
   422  			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
   423  		}
   424  
   425  		// Test Reader.Reset.
   426  		in = bytes.NewReader(tt.gzip)
   427  		err = r1.Reset(in)
   428  		if err != nil {
   429  			t.Errorf("%s: Reset: %s", tt.desc, err)
   430  			continue
   431  		}
   432  		if tt.name != r1.Name {
   433  			t.Errorf("%s: got name %s", tt.desc, r1.Name)
   434  		}
   435  		b.Reset()
   436  		n, err = io.Copy(b, r1)
   437  		if err != tt.err {
   438  			t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
   439  		}
   440  		s = b.String()
   441  		if s != tt.raw {
   442  			t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
   443  		}
   444  	}
   445  }
   446  
   447  func TestIssue6550(t *testing.T) {
   448  	// Apple’s notarization service will recursively attempt to decompress
   449  	// files in order to find binaries to notarize. Since the service is
   450  	// unable to decompress this file, it may reject the entire toolchain. Use a
   451  	// base64-encoded version to avoid this.
   452  	// See golang.org/issue/34986
   453  	f, err := os.Open("testdata/issue6550.gz.base64")
   454  	if err != nil {
   455  		t.Fatal(err)
   456  	}
   457  	gzip, err := NewReader(base64.NewDecoder(base64.StdEncoding, f))
   458  	if err != nil {
   459  		t.Fatalf("NewReader(testdata/issue6550.gz): %v", err)
   460  	}
   461  	defer gzip.Close()
   462  	done := make(chan bool, 1)
   463  	go func() {
   464  		_, err := io.Copy(io.Discard, gzip)
   465  		if err == nil {
   466  			t.Errorf("Copy succeeded")
   467  		} else {
   468  			t.Logf("Copy failed (correctly): %v", err)
   469  		}
   470  		done <- true
   471  	}()
   472  	select {
   473  	case <-time.After(1 * time.Second):
   474  		t.Errorf("Copy hung")
   475  	case <-done:
   476  		// ok
   477  	}
   478  }
   479  
   480  func TestMultistreamFalse(t *testing.T) {
   481  	// Find concatenation test.
   482  	var tt gunzipTest
   483  	for _, tt = range gunzipTests {
   484  		if strings.HasSuffix(tt.desc, " x2") {
   485  			goto Found
   486  		}
   487  	}
   488  	t.Fatal("cannot find hello.txt x2 in gunzip tests")
   489  
   490  Found:
   491  	br := bytes.NewReader(tt.gzip)
   492  	var r Reader
   493  	if err := r.Reset(br); err != nil {
   494  		t.Fatalf("first reset: %v", err)
   495  	}
   496  
   497  	// Expect two streams with "hello world\n", then real EOF.
   498  	const hello = "hello world\n"
   499  
   500  	r.Multistream(false)
   501  	data, err := io.ReadAll(&r)
   502  	if string(data) != hello || err != nil {
   503  		t.Fatalf("first stream = %q, %v, want %q, %v", string(data), err, hello, nil)
   504  	}
   505  
   506  	if err := r.Reset(br); err != nil {
   507  		t.Fatalf("second reset: %v", err)
   508  	}
   509  	r.Multistream(false)
   510  	data, err = io.ReadAll(&r)
   511  	if string(data) != hello || err != nil {
   512  		t.Fatalf("second stream = %q, %v, want %q, %v", string(data), err, hello, nil)
   513  	}
   514  
   515  	if err := r.Reset(br); err != io.EOF {
   516  		t.Fatalf("third reset: err=%v, want io.EOF", err)
   517  	}
   518  }
   519  
   520  func TestNilStream(t *testing.T) {
   521  	// Go liberally interprets RFC 1952 section 2.2 to mean that a gzip file
   522  	// consist of zero or more members. Thus, we test that a nil stream is okay.
   523  	_, err := NewReader(bytes.NewReader(nil))
   524  	if err != io.EOF {
   525  		t.Fatalf("NewReader(nil) on empty stream: got %v, want io.EOF", err)
   526  	}
   527  }
   528  
   529  func TestTruncatedStreams(t *testing.T) {
   530  	cases := []struct {
   531  		name string
   532  		data []byte
   533  	}{
   534  		{
   535  			name: "original",
   536  			data: []byte("\x1f\x8b\b\x04\x00\tn\x88\x00\xff\a\x00foo bar\xcbH\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x04:r\xab\xff\f\x00\x00\x00"),
   537  		},
   538  		{
   539  			name: "truncated name",
   540  			data: []byte{
   541  				0x1f, 0x8b, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
   542  			},
   543  		},
   544  		{
   545  			name: "truncated comment",
   546  			data: []byte{
   547  				0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01,
   548  			},
   549  		},
   550  	}
   551  
   552  	// Intentionally iterate starting with at least one byte in the stream.
   553  	for _, tc := range cases {
   554  		for i := 1; i < len(tc.data); i++ {
   555  			r, err := NewReader(strings.NewReader(string(tc.data[:i])))
   556  			if err != nil {
   557  				if err != io.ErrUnexpectedEOF {
   558  					t.Errorf("NewReader(%s-%d) on truncated stream: got %v, want %v", tc.name, i, err, io.ErrUnexpectedEOF)
   559  				}
   560  				continue
   561  			}
   562  			_, err = io.Copy(io.Discard, r)
   563  			if ferr, ok := err.(*flate.ReadError); ok {
   564  				err = ferr.Err
   565  			}
   566  			if err != io.ErrUnexpectedEOF {
   567  				t.Errorf("io.Copy(%s-%d) on truncated stream: got %v, want %v", tc.name, i, err, io.ErrUnexpectedEOF)
   568  			}
   569  		}
   570  	}
   571  }
   572  
   573  func TestCVE202230631(t *testing.T) {
   574  	var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00,
   575  		0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
   576  	r := bytes.NewReader(bytes.Repeat(empty, 4e6))
   577  	z, err := NewReader(r)
   578  	if err != nil {
   579  		t.Fatalf("NewReader: got %v, want nil", err)
   580  	}
   581  	// Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due
   582  	// to stack exhaustion.
   583  	_, err = z.Read(make([]byte, 10))
   584  	if err != io.EOF {
   585  		t.Errorf("Reader.Read: got %v, want %v", err, io.EOF)
   586  	}
   587  }
   588  

View as plain text