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
5package gzip
6
7import (
8	"bytes"
9	"compress/flate"
10	"encoding/base64"
11	"io"
12	"os"
13	"strings"
14	"testing"
15	"time"
16)
17
18type gunzipTest struct {
19	name string
20	desc string
21	raw  string
22	gzip []byte
23	err  error
24}
25
26var 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
396func 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
447func 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
480func 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
490Found:
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
520func 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
529func 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
573func 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