~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/zip/reader_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2010 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 zip
 
6
 
 
7
import (
 
8
        "bytes"
 
9
        "encoding/binary"
 
10
        "encoding/hex"
 
11
        "io"
 
12
        "io/ioutil"
 
13
        "os"
 
14
        "path/filepath"
 
15
        "regexp"
 
16
        "strings"
 
17
        "testing"
 
18
        "time"
 
19
)
 
20
 
 
21
type ZipTest struct {
 
22
        Name    string
 
23
        Source  func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/<Name> file
 
24
        Comment string
 
25
        File    []ZipTestFile
 
26
        Error   error // the error that Opening this file should return
 
27
}
 
28
 
 
29
type ZipTestFile struct {
 
30
        Name       string
 
31
        Content    []byte // if blank, will attempt to compare against File
 
32
        ContentErr error
 
33
        File       string // name of file to compare to (relative to testdata/)
 
34
        Mtime      string // modified time in format "mm-dd-yy hh:mm:ss"
 
35
        Mode       os.FileMode
 
36
}
 
37
 
 
38
// Caution: The Mtime values found for the test files should correspond to
 
39
//          the values listed with unzip -l <zipfile>. However, the values
 
40
//          listed by unzip appear to be off by some hours. When creating
 
41
//          fresh test files and testing them, this issue is not present.
 
42
//          The test files were created in Sydney, so there might be a time
 
43
//          zone issue. The time zone information does have to be encoded
 
44
//          somewhere, because otherwise unzip -l could not provide a different
 
45
//          time from what the archive/zip package provides, but there appears
 
46
//          to be no documentation about this.
 
47
 
 
48
var tests = []ZipTest{
 
49
        {
 
50
                Name:    "test.zip",
 
51
                Comment: "This is a zipfile comment.",
 
52
                File: []ZipTestFile{
 
53
                        {
 
54
                                Name:    "test.txt",
 
55
                                Content: []byte("This is a test text file.\n"),
 
56
                                Mtime:   "09-05-10 12:12:02",
 
57
                                Mode:    0644,
 
58
                        },
 
59
                        {
 
60
                                Name:  "gophercolor16x16.png",
 
61
                                File:  "gophercolor16x16.png",
 
62
                                Mtime: "09-05-10 15:52:58",
 
63
                                Mode:  0644,
 
64
                        },
 
65
                },
 
66
        },
 
67
        {
 
68
                Name:    "test-trailing-junk.zip",
 
69
                Comment: "This is a zipfile comment.",
 
70
                File: []ZipTestFile{
 
71
                        {
 
72
                                Name:    "test.txt",
 
73
                                Content: []byte("This is a test text file.\n"),
 
74
                                Mtime:   "09-05-10 12:12:02",
 
75
                                Mode:    0644,
 
76
                        },
 
77
                        {
 
78
                                Name:  "gophercolor16x16.png",
 
79
                                File:  "gophercolor16x16.png",
 
80
                                Mtime: "09-05-10 15:52:58",
 
81
                                Mode:  0644,
 
82
                        },
 
83
                },
 
84
        },
 
85
        {
 
86
                Name:   "r.zip",
 
87
                Source: returnRecursiveZip,
 
88
                File: []ZipTestFile{
 
89
                        {
 
90
                                Name:    "r/r.zip",
 
91
                                Content: rZipBytes(),
 
92
                                Mtime:   "03-04-10 00:24:16",
 
93
                                Mode:    0666,
 
94
                        },
 
95
                },
 
96
        },
 
97
        {
 
98
                Name: "symlink.zip",
 
99
                File: []ZipTestFile{
 
100
                        {
 
101
                                Name:    "symlink",
 
102
                                Content: []byte("../target"),
 
103
                                Mode:    0777 | os.ModeSymlink,
 
104
                        },
 
105
                },
 
106
        },
 
107
        {
 
108
                Name: "readme.zip",
 
109
        },
 
110
        {
 
111
                Name:  "readme.notzip",
 
112
                Error: ErrFormat,
 
113
        },
 
114
        {
 
115
                Name: "dd.zip",
 
116
                File: []ZipTestFile{
 
117
                        {
 
118
                                Name:    "filename",
 
119
                                Content: []byte("This is a test textfile.\n"),
 
120
                                Mtime:   "02-02-11 13:06:20",
 
121
                                Mode:    0666,
 
122
                        },
 
123
                },
 
124
        },
 
125
        {
 
126
                // created in windows XP file manager.
 
127
                Name: "winxp.zip",
 
128
                File: crossPlatform,
 
129
        },
 
130
        {
 
131
                // created by Zip 3.0 under Linux
 
132
                Name: "unix.zip",
 
133
                File: crossPlatform,
 
134
        },
 
135
        {
 
136
                // created by Go, before we wrote the "optional" data
 
137
                // descriptor signatures (which are required by OS X)
 
138
                Name: "go-no-datadesc-sig.zip",
 
139
                File: []ZipTestFile{
 
140
                        {
 
141
                                Name:    "foo.txt",
 
142
                                Content: []byte("foo\n"),
 
143
                                Mtime:   "03-08-12 16:59:10",
 
144
                                Mode:    0644,
 
145
                        },
 
146
                        {
 
147
                                Name:    "bar.txt",
 
148
                                Content: []byte("bar\n"),
 
149
                                Mtime:   "03-08-12 16:59:12",
 
150
                                Mode:    0644,
 
151
                        },
 
152
                },
 
153
        },
 
154
        {
 
155
                // created by Go, after we wrote the "optional" data
 
156
                // descriptor signatures (which are required by OS X)
 
157
                Name: "go-with-datadesc-sig.zip",
 
158
                File: []ZipTestFile{
 
159
                        {
 
160
                                Name:    "foo.txt",
 
161
                                Content: []byte("foo\n"),
 
162
                                Mode:    0666,
 
163
                        },
 
164
                        {
 
165
                                Name:    "bar.txt",
 
166
                                Content: []byte("bar\n"),
 
167
                                Mode:    0666,
 
168
                        },
 
169
                },
 
170
        },
 
171
        {
 
172
                Name:   "Bad-CRC32-in-data-descriptor",
 
173
                Source: returnCorruptCRC32Zip,
 
174
                File: []ZipTestFile{
 
175
                        {
 
176
                                Name:       "foo.txt",
 
177
                                Content:    []byte("foo\n"),
 
178
                                Mode:       0666,
 
179
                                ContentErr: ErrChecksum,
 
180
                        },
 
181
                        {
 
182
                                Name:    "bar.txt",
 
183
                                Content: []byte("bar\n"),
 
184
                                Mode:    0666,
 
185
                        },
 
186
                },
 
187
        },
 
188
        // Tests that we verify (and accept valid) crc32s on files
 
189
        // with crc32s in their file header (not in data descriptors)
 
190
        {
 
191
                Name: "crc32-not-streamed.zip",
 
192
                File: []ZipTestFile{
 
193
                        {
 
194
                                Name:    "foo.txt",
 
195
                                Content: []byte("foo\n"),
 
196
                                Mtime:   "03-08-12 16:59:10",
 
197
                                Mode:    0644,
 
198
                        },
 
199
                        {
 
200
                                Name:    "bar.txt",
 
201
                                Content: []byte("bar\n"),
 
202
                                Mtime:   "03-08-12 16:59:12",
 
203
                                Mode:    0644,
 
204
                        },
 
205
                },
 
206
        },
 
207
        // Tests that we verify (and reject invalid) crc32s on files
 
208
        // with crc32s in their file header (not in data descriptors)
 
209
        {
 
210
                Name:   "crc32-not-streamed.zip",
 
211
                Source: returnCorruptNotStreamedZip,
 
212
                File: []ZipTestFile{
 
213
                        {
 
214
                                Name:       "foo.txt",
 
215
                                Content:    []byte("foo\n"),
 
216
                                Mtime:      "03-08-12 16:59:10",
 
217
                                Mode:       0644,
 
218
                                ContentErr: ErrChecksum,
 
219
                        },
 
220
                        {
 
221
                                Name:    "bar.txt",
 
222
                                Content: []byte("bar\n"),
 
223
                                Mtime:   "03-08-12 16:59:12",
 
224
                                Mode:    0644,
 
225
                        },
 
226
                },
 
227
        },
 
228
        {
 
229
                Name: "zip64.zip",
 
230
                File: []ZipTestFile{
 
231
                        {
 
232
                                Name:    "README",
 
233
                                Content: []byte("This small file is in ZIP64 format.\n"),
 
234
                                Mtime:   "08-10-12 14:33:32",
 
235
                                Mode:    0644,
 
236
                        },
 
237
                },
 
238
        },
 
239
        // Another zip64 file with different Extras fields. (golang.org/issue/7069)
 
240
        {
 
241
                Name: "zip64-2.zip",
 
242
                File: []ZipTestFile{
 
243
                        {
 
244
                                Name:    "README",
 
245
                                Content: []byte("This small file is in ZIP64 format.\n"),
 
246
                                Mtime:   "08-10-12 14:33:32",
 
247
                                Mode:    0644,
 
248
                        },
 
249
                },
 
250
        },
 
251
}
 
252
 
 
253
var crossPlatform = []ZipTestFile{
 
254
        {
 
255
                Name:    "hello",
 
256
                Content: []byte("world \r\n"),
 
257
                Mode:    0666,
 
258
        },
 
259
        {
 
260
                Name:    "dir/bar",
 
261
                Content: []byte("foo \r\n"),
 
262
                Mode:    0666,
 
263
        },
 
264
        {
 
265
                Name:    "dir/empty/",
 
266
                Content: []byte{},
 
267
                Mode:    os.ModeDir | 0777,
 
268
        },
 
269
        {
 
270
                Name:    "readonly",
 
271
                Content: []byte("important \r\n"),
 
272
                Mode:    0444,
 
273
        },
 
274
}
 
275
 
 
276
func TestReader(t *testing.T) {
 
277
        for _, zt := range tests {
 
278
                readTestZip(t, zt)
 
279
        }
 
280
}
 
281
 
 
282
func readTestZip(t *testing.T, zt ZipTest) {
 
283
        var z *Reader
 
284
        var err error
 
285
        if zt.Source != nil {
 
286
                rat, size := zt.Source()
 
287
                z, err = NewReader(rat, size)
 
288
        } else {
 
289
                var rc *ReadCloser
 
290
                rc, err = OpenReader(filepath.Join("testdata", zt.Name))
 
291
                if err == nil {
 
292
                        defer rc.Close()
 
293
                        z = &rc.Reader
 
294
                }
 
295
        }
 
296
        if err != zt.Error {
 
297
                t.Errorf("%s: error=%v, want %v", zt.Name, err, zt.Error)
 
298
                return
 
299
        }
 
300
 
 
301
        // bail if file is not zip
 
302
        if err == ErrFormat {
 
303
                return
 
304
        }
 
305
 
 
306
        // bail here if no Files expected to be tested
 
307
        // (there may actually be files in the zip, but we don't care)
 
308
        if zt.File == nil {
 
309
                return
 
310
        }
 
311
 
 
312
        if z.Comment != zt.Comment {
 
313
                t.Errorf("%s: comment=%q, want %q", zt.Name, z.Comment, zt.Comment)
 
314
        }
 
315
        if len(z.File) != len(zt.File) {
 
316
                t.Fatalf("%s: file count=%d, want %d", zt.Name, len(z.File), len(zt.File))
 
317
        }
 
318
 
 
319
        // test read of each file
 
320
        for i, ft := range zt.File {
 
321
                readTestFile(t, zt, ft, z.File[i])
 
322
        }
 
323
 
 
324
        // test simultaneous reads
 
325
        n := 0
 
326
        done := make(chan bool)
 
327
        for i := 0; i < 5; i++ {
 
328
                for j, ft := range zt.File {
 
329
                        go func(j int, ft ZipTestFile) {
 
330
                                readTestFile(t, zt, ft, z.File[j])
 
331
                                done <- true
 
332
                        }(j, ft)
 
333
                        n++
 
334
                }
 
335
        }
 
336
        for ; n > 0; n-- {
 
337
                <-done
 
338
        }
 
339
}
 
340
 
 
341
func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
 
342
        if f.Name != ft.Name {
 
343
                t.Errorf("%s: name=%q, want %q", zt.Name, f.Name, ft.Name)
 
344
        }
 
345
 
 
346
        if ft.Mtime != "" {
 
347
                mtime, err := time.Parse("01-02-06 15:04:05", ft.Mtime)
 
348
                if err != nil {
 
349
                        t.Error(err)
 
350
                        return
 
351
                }
 
352
                if ft := f.ModTime(); !ft.Equal(mtime) {
 
353
                        t.Errorf("%s: %s: mtime=%s, want %s", zt.Name, f.Name, ft, mtime)
 
354
                }
 
355
        }
 
356
 
 
357
        testFileMode(t, zt.Name, f, ft.Mode)
 
358
 
 
359
        var b bytes.Buffer
 
360
        r, err := f.Open()
 
361
        if err != nil {
 
362
                t.Errorf("%s: %v", zt.Name, err)
 
363
                return
 
364
        }
 
365
 
 
366
        _, err = io.Copy(&b, r)
 
367
        if err != ft.ContentErr {
 
368
                t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr)
 
369
        }
 
370
        if err != nil {
 
371
                return
 
372
        }
 
373
        r.Close()
 
374
 
 
375
        size := uint64(f.UncompressedSize)
 
376
        if size == uint32max {
 
377
                size = f.UncompressedSize64
 
378
        }
 
379
        if g := uint64(b.Len()); g != size {
 
380
                t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size)
 
381
        }
 
382
 
 
383
        var c []byte
 
384
        if ft.Content != nil {
 
385
                c = ft.Content
 
386
        } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
 
387
                t.Error(err)
 
388
                return
 
389
        }
 
390
 
 
391
        if b.Len() != len(c) {
 
392
                t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c))
 
393
                return
 
394
        }
 
395
 
 
396
        for i, b := range b.Bytes() {
 
397
                if b != c[i] {
 
398
                        t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
 
399
                        return
 
400
                }
 
401
        }
 
402
}
 
403
 
 
404
func testFileMode(t *testing.T, zipName string, f *File, want os.FileMode) {
 
405
        mode := f.Mode()
 
406
        if want == 0 {
 
407
                t.Errorf("%s: %s mode: got %v, want none", zipName, f.Name, mode)
 
408
        } else if mode != want {
 
409
                t.Errorf("%s: %s mode: want %v, got %v", zipName, f.Name, want, mode)
 
410
        }
 
411
}
 
412
 
 
413
func TestInvalidFiles(t *testing.T) {
 
414
        const size = 1024 * 70 // 70kb
 
415
        b := make([]byte, size)
 
416
 
 
417
        // zeroes
 
418
        _, err := NewReader(bytes.NewReader(b), size)
 
419
        if err != ErrFormat {
 
420
                t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
 
421
        }
 
422
 
 
423
        // repeated directoryEndSignatures
 
424
        sig := make([]byte, 4)
 
425
        binary.LittleEndian.PutUint32(sig, directoryEndSignature)
 
426
        for i := 0; i < size-4; i += 4 {
 
427
                copy(b[i:i+4], sig)
 
428
        }
 
429
        _, err = NewReader(bytes.NewReader(b), size)
 
430
        if err != ErrFormat {
 
431
                t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
 
432
        }
 
433
}
 
434
 
 
435
func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
 
436
        data, err := ioutil.ReadFile(filepath.Join("testdata", fileName))
 
437
        if err != nil {
 
438
                panic("Error reading " + fileName + ": " + err.Error())
 
439
        }
 
440
        corrupter(data)
 
441
        return bytes.NewReader(data), int64(len(data))
 
442
}
 
443
 
 
444
func returnCorruptCRC32Zip() (r io.ReaderAt, size int64) {
 
445
        return messWith("go-with-datadesc-sig.zip", func(b []byte) {
 
446
                // Corrupt one of the CRC32s in the data descriptor:
 
447
                b[0x2d]++
 
448
        })
 
449
}
 
450
 
 
451
func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) {
 
452
        return messWith("crc32-not-streamed.zip", func(b []byte) {
 
453
                // Corrupt foo.txt's final crc32 byte, in both
 
454
                // the file header and TOC. (0x7e -> 0x7f)
 
455
                b[0x11]++
 
456
                b[0x9d]++
 
457
 
 
458
                // TODO(bradfitz): add a new test that only corrupts
 
459
                // one of these values, and verify that that's also an
 
460
                // error. Currently, the reader code doesn't verify the
 
461
                // fileheader and TOC's crc32 match if they're both
 
462
                // non-zero and only the second line above, the TOC,
 
463
                // is what matters.
 
464
        })
 
465
}
 
466
 
 
467
// rZipBytes returns the bytes of a recursive zip file, without
 
468
// putting it on disk and triggering certain virus scanners.
 
469
func rZipBytes() []byte {
 
470
        s := `
 
471
0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4
 
472
0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f
 
473
0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00
 
474
0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00
 
475
0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00
 
476
0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00
 
477
0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8
 
478
0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f
 
479
0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e
 
480
0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb
 
481
00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff
 
482
00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42
 
483
00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14
 
484
00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21
 
485
00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb
 
486
00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff
 
487
0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a
 
488
0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3
 
489
0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06
 
490
0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00
 
491
0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf
 
492
0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06
 
493
0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01
 
494
0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89
 
495
0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00
 
496
0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a
 
497
00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00
 
498
00001b0 00 00 6d 01 00 00 00 00`
 
499
        s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
 
500
        s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
 
501
        b, err := hex.DecodeString(s)
 
502
        if err != nil {
 
503
                panic(err)
 
504
        }
 
505
        return b
 
506
}
 
507
 
 
508
func returnRecursiveZip() (r io.ReaderAt, size int64) {
 
509
        b := rZipBytes()
 
510
        return bytes.NewReader(b), int64(len(b))
 
511
}
 
512
 
 
513
func TestIssue8186(t *testing.T) {
 
514
        // Directory headers & data found in the TOC of a JAR file.
 
515
        dirEnts := []string{
 
516
                "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\xaa\x1b\x06\xf0\x81\x02\x00\x00\x81\x02\x00\x00-\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00res/drawable-xhdpi-v4/ic_actionbar_accept.png\xfe\xca\x00\x00\x00",
 
517
                "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\x90K\x89\xc7t\n\x00\x00t\n\x00\x00\x0e\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x02\x00\x00resources.arsc\x00\x00\x00",
 
518
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xff$\x18\xed3\x03\x00\x00\xb4\b\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\r\x00\x00AndroidManifest.xml",
 
519
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\x14\xc5K\xab\x192\x02\x00\xc8\xcd\x04\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x10\x00\x00classes.dex",
 
520
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?E\x96\nD\xac\x01\x00\x00P\x03\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:C\x02\x00res/layout/actionbar_set_wallpaper.xml",
 
521
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?Ļ\x14\xe3\xd8\x01\x00\x00\xd8\x03\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:E\x02\x00res/layout/wallpaper_cropper.xml",
 
522
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?}\xc1\x15\x9eZ\x01\x00\x00!\x02\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`G\x02\x00META-INF/MANIFEST.MF",
 
523
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xe6\x98Ьo\x01\x00\x00\x84\x02\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfcH\x02\x00META-INF/CERT.SF",
 
524
                "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xbfP\x96b\x86\x04\x00\x00\xb2\x06\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9J\x02\x00META-INF/CERT.RSA",
 
525
        }
 
526
        for i, s := range dirEnts {
 
527
                var f File
 
528
                err := readDirectoryHeader(&f, strings.NewReader(s))
 
529
                if err != nil {
 
530
                        t.Errorf("error reading #%d: %v", i, err)
 
531
                }
 
532
        }
 
533
}
 
534
 
 
535
// Verify we return ErrUnexpectedEOF when length is short.
 
536
func TestIssue10957(t *testing.T) {
 
537
        data := []byte("PK\x03\x040000000PK\x01\x0200000" +
 
538
                "0000000000000000000\x00" +
 
539
                "\x00\x00\x00\x00\x00000000000000PK\x01" +
 
540
                "\x020000000000000000000" +
 
541
                "00000\v\x00\x00\x00\x00\x00000000000" +
 
542
                "00000000000000PK\x01\x0200" +
 
543
                "00000000000000000000" +
 
544
                "00\v\x00\x00\x00\x00\x00000000000000" +
 
545
                "00000000000PK\x01\x020000<" +
 
546
                "0\x00\x0000000000000000\v\x00\v" +
 
547
                "\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
 
548
                "00000000PK\x01\x0200000000" +
 
549
                "0000000000000000\v\x00\x00\x00" +
 
550
                "\x00\x0000PK\x05\x06000000\x05\x000000" +
 
551
                "\v\x00\x00\x00\x00\x00")
 
552
        z, err := NewReader(bytes.NewReader(data), int64(len(data)))
 
553
        if err != nil {
 
554
                t.Fatal(err)
 
555
        }
 
556
        for i, f := range z.File {
 
557
                r, err := f.Open()
 
558
                if err != nil {
 
559
                        continue
 
560
                }
 
561
                if f.UncompressedSize64 < 1e6 {
 
562
                        n, err := io.Copy(ioutil.Discard, r)
 
563
                        if i == 3 && err != io.ErrUnexpectedEOF {
 
564
                                t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
 
565
                        }
 
566
                        if err == nil && uint64(n) != f.UncompressedSize64 {
 
567
                                t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64)
 
568
                        }
 
569
                }
 
570
                r.Close()
 
571
        }
 
572
}
 
573
 
 
574
// Verify the number of files is sane.
 
575
func TestIssue10956(t *testing.T) {
 
576
        data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" +
 
577
                "0000PK\x05\x06000000000000" +
 
578
                "0000\v\x00000\x00\x00\x00\x00\x00\x00\x000")
 
579
        _, err := NewReader(bytes.NewReader(data), int64(len(data)))
 
580
        const want = "TOC declares impossible 3472328296227680304 files in 57 byte"
 
581
        if err == nil && !strings.Contains(err.Error(), want) {
 
582
                t.Errorf("error = %v; want %q", err, want)
 
583
        }
 
584
}
 
585
 
 
586
// Verify we return ErrUnexpectedEOF when reading truncated data descriptor.
 
587
func TestIssue11146(t *testing.T) {
 
588
        data := []byte("PK\x03\x040000000000000000" +
 
589
                "000000\x01\x00\x00\x000\x01\x00\x00\xff\xff0000" +
 
590
                "0000000000000000PK\x01\x02" +
 
591
                "0000\b0\b\x00000000000000" +
 
592
                "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" +
 
593
                "\x00\x0000\x01\x0000008\x00\x00\x00\x00\x00")
 
594
        z, err := NewReader(bytes.NewReader(data), int64(len(data)))
 
595
        if err != nil {
 
596
                t.Fatal(err)
 
597
        }
 
598
        r, err := z.File[0].Open()
 
599
        if err != nil {
 
600
                t.Fatal(err)
 
601
        }
 
602
        _, err = ioutil.ReadAll(r)
 
603
        if err != io.ErrUnexpectedEOF {
 
604
                t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
 
605
        }
 
606
        r.Close()
 
607
}
 
608
 
 
609
// Verify we do not treat non-zip64 archives as zip64
 
610
func TestIssue12449(t *testing.T) {
 
611
        data := []byte{
 
612
                0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
 
613
                0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46, 0x00, 0x00,
 
614
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
615
                0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0xca, 0x64,
 
616
                0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
 
617
                0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
 
618
                0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
 
619
                0x00, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x0a,
 
620
                0x50, 0x4b, 0x07, 0x08, 0x1d, 0x88, 0x77, 0xb0,
 
621
                0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
 
622
                0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00,
 
623
                0x08, 0x00, 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46,
 
624
                0x1d, 0x88, 0x77, 0xb0, 0x07, 0x00, 0x00, 0x00,
 
625
                0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00,
 
626
                0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
627
                0xa0, 0x81, 0x00, 0x00, 0x00, 0x00, 0xca, 0x64,
 
628
                0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
 
629
                0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
 
630
                0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
 
631
                0x00, 0x97, 0x2b, 0x49, 0x23, 0x05, 0xc5, 0x0b,
 
632
                0xa7, 0xd1, 0x52, 0xa2, 0x9c, 0x50, 0x4b, 0x06,
 
633
                0x07, 0xc8, 0x19, 0xc1, 0xaf, 0x94, 0x9c, 0x61,
 
634
                0x44, 0xbe, 0x94, 0x19, 0x42, 0x58, 0x12, 0xc6,
 
635
                0x5b, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00,
 
636
                0x00, 0x01, 0x00, 0x01, 0x00, 0x69, 0x00, 0x00,
 
637
                0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
 
638
        }
 
639
        // Read in the archive.
 
640
        _, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
 
641
        if err != nil {
 
642
                t.Errorf("Error reading the archive: %v", err)
 
643
        }
 
644
}