1
2
3
4
5 package zip
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "encoding/hex"
11 "io"
12 "io/fs"
13 "os"
14 "path/filepath"
15 "reflect"
16 "regexp"
17 "strings"
18 "testing"
19 "testing/fstest"
20 "time"
21
22 "github.com/klauspost/compress/zip/internal/obscuretestdata"
23 )
24
25 type ZipTest struct {
26 Name string
27 Source func() (r io.ReaderAt, size int64)
28 Comment string
29 File []ZipTestFile
30 Obscured bool
31 Error error
32 }
33
34 type ZipTestFile struct {
35 Name string
36 Mode fs.FileMode
37 NonUTF8 bool
38 ModTime time.Time
39 Modified time.Time
40
41
42
43
44
45
46
47
48
49
50
51 ContentErr error
52 Content []byte
53 File string
54 Size uint64
55 }
56
57 var tests = []ZipTest{
58 {
59 Name: "test.zip",
60 Comment: "This is a zipfile comment.",
61 File: []ZipTestFile{
62 {
63 Name: "test.txt",
64 Content: []byte("This is a test text file.\n"),
65 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
66 Mode: 0644,
67 },
68 {
69 Name: "gophercolor16x16.png",
70 File: "gophercolor16x16.png",
71 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
72 Mode: 0644,
73 },
74 },
75 },
76 {
77 Name: "test-trailing-junk.zip",
78 Comment: "This is a zipfile comment.",
79 File: []ZipTestFile{
80 {
81 Name: "test.txt",
82 Content: []byte("This is a test text file.\n"),
83 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
84 Mode: 0644,
85 },
86 {
87 Name: "gophercolor16x16.png",
88 File: "gophercolor16x16.png",
89 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
90 Mode: 0644,
91 },
92 },
93 },
94 {
95 Name: "test-prefix.zip",
96 Comment: "This is a zipfile comment.",
97 File: []ZipTestFile{
98 {
99 Name: "test.txt",
100 Content: []byte("This is a test text file.\n"),
101 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
102 Mode: 0644,
103 },
104 {
105 Name: "gophercolor16x16.png",
106 File: "gophercolor16x16.png",
107 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
108 Mode: 0644,
109 },
110 },
111 },
112 {
113 Name: "test-baddirsz.zip",
114 Comment: "This is a zipfile comment.",
115 File: []ZipTestFile{
116 {
117 Name: "test.txt",
118 Content: []byte("This is a test text file.\n"),
119 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)),
120 Mode: 0644,
121 },
122 {
123 Name: "gophercolor16x16.png",
124 File: "gophercolor16x16.png",
125 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)),
126 Mode: 0644,
127 },
128 },
129 },
130 {
131 Name: "r.zip",
132 Source: returnRecursiveZip,
133 File: []ZipTestFile{
134 {
135 Name: "r/r.zip",
136 Content: rZipBytes(),
137 Modified: time.Date(2010, 3, 4, 0, 24, 16, 0, time.UTC),
138 Mode: 0666,
139 },
140 },
141 },
142 {
143 Name: "symlink.zip",
144 File: []ZipTestFile{
145 {
146 Name: "symlink",
147 Content: []byte("../target"),
148 Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)),
149 Mode: 0777 | fs.ModeSymlink,
150 },
151 },
152 },
153 {
154 Name: "readme.zip",
155 },
156 {
157 Name: "readme.notzip",
158 Error: ErrFormat,
159 },
160 {
161 Name: "dd.zip",
162 File: []ZipTestFile{
163 {
164 Name: "filename",
165 Content: []byte("This is a test textfile.\n"),
166 Modified: time.Date(2011, 2, 2, 13, 6, 20, 0, time.UTC),
167 Mode: 0666,
168 },
169 },
170 },
171 {
172
173 Name: "winxp.zip",
174 File: []ZipTestFile{
175 {
176 Name: "hello",
177 Content: []byte("world \r\n"),
178 Modified: time.Date(2011, 12, 8, 10, 4, 24, 0, time.UTC),
179 Mode: 0666,
180 },
181 {
182 Name: "dir/bar",
183 Content: []byte("foo \r\n"),
184 Modified: time.Date(2011, 12, 8, 10, 4, 50, 0, time.UTC),
185 Mode: 0666,
186 },
187 {
188 Name: "dir/empty/",
189 Content: []byte{},
190 Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC),
191 Mode: fs.ModeDir | 0777,
192 },
193 {
194 Name: "readonly",
195 Content: []byte("important \r\n"),
196 Modified: time.Date(2011, 12, 8, 10, 6, 8, 0, time.UTC),
197 Mode: 0444,
198 },
199 },
200 },
201 {
202
203 Name: "unix.zip",
204 File: []ZipTestFile{
205 {
206 Name: "hello",
207 Content: []byte("world \r\n"),
208 Modified: time.Date(2011, 12, 8, 10, 4, 24, 0, timeZone(0)),
209 Mode: 0666,
210 },
211 {
212 Name: "dir/bar",
213 Content: []byte("foo \r\n"),
214 Modified: time.Date(2011, 12, 8, 10, 4, 50, 0, timeZone(0)),
215 Mode: 0666,
216 },
217 {
218 Name: "dir/empty/",
219 Content: []byte{},
220 Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)),
221 Mode: fs.ModeDir | 0777,
222 },
223 {
224 Name: "readonly",
225 Content: []byte("important \r\n"),
226 Modified: time.Date(2011, 12, 8, 10, 6, 8, 0, timeZone(0)),
227 Mode: 0444,
228 },
229 },
230 },
231 {
232
233
234
235
236
237 Name: "go-no-datadesc-sig.zip.base64",
238 Obscured: true,
239 File: []ZipTestFile{
240 {
241 Name: "foo.txt",
242 Content: []byte("foo\n"),
243 Modified: time.Date(2012, 3, 8, 16, 59, 10, 0, timeZone(-8*time.Hour)),
244 Mode: 0644,
245 },
246 {
247 Name: "bar.txt",
248 Content: []byte("bar\n"),
249 Modified: time.Date(2012, 3, 8, 16, 59, 12, 0, timeZone(-8*time.Hour)),
250 Mode: 0644,
251 },
252 },
253 },
254 {
255
256
257 Name: "go-with-datadesc-sig.zip",
258 File: []ZipTestFile{
259 {
260 Name: "foo.txt",
261 Content: []byte("foo\n"),
262 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC),
263 Mode: 0666,
264 },
265 {
266 Name: "bar.txt",
267 Content: []byte("bar\n"),
268 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC),
269 Mode: 0666,
270 },
271 },
272 },
273 {
274 Name: "Bad-CRC32-in-data-descriptor",
275 Source: returnCorruptCRC32Zip,
276 File: []ZipTestFile{
277 {
278 Name: "foo.txt",
279 Content: []byte("foo\n"),
280 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC),
281 Mode: 0666,
282 ContentErr: ErrChecksum,
283 },
284 {
285 Name: "bar.txt",
286 Content: []byte("bar\n"),
287 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC),
288 Mode: 0666,
289 },
290 },
291 },
292
293
294 {
295 Name: "crc32-not-streamed.zip",
296 File: []ZipTestFile{
297 {
298 Name: "foo.txt",
299 Content: []byte("foo\n"),
300 Modified: time.Date(2012, 3, 8, 16, 59, 10, 0, timeZone(-8*time.Hour)),
301 Mode: 0644,
302 },
303 {
304 Name: "bar.txt",
305 Content: []byte("bar\n"),
306 Modified: time.Date(2012, 3, 8, 16, 59, 12, 0, timeZone(-8*time.Hour)),
307 Mode: 0644,
308 },
309 },
310 },
311
312
313 {
314 Name: "crc32-not-streamed.zip",
315 Source: returnCorruptNotStreamedZip,
316 File: []ZipTestFile{
317 {
318 Name: "foo.txt",
319 Content: []byte("foo\n"),
320 Modified: time.Date(2012, 3, 8, 16, 59, 10, 0, timeZone(-8*time.Hour)),
321 Mode: 0644,
322 ContentErr: ErrChecksum,
323 },
324 {
325 Name: "bar.txt",
326 Content: []byte("bar\n"),
327 Modified: time.Date(2012, 3, 8, 16, 59, 12, 0, timeZone(-8*time.Hour)),
328 Mode: 0644,
329 },
330 },
331 },
332 {
333 Name: "zip64.zip",
334 File: []ZipTestFile{
335 {
336 Name: "README",
337 Content: []byte("This small file is in ZIP64 format.\n"),
338 Modified: time.Date(2012, 8, 10, 14, 33, 32, 0, time.UTC),
339 Mode: 0644,
340 },
341 },
342 },
343
344 {
345 Name: "zip64-2.zip",
346 File: []ZipTestFile{
347 {
348 Name: "README",
349 Content: []byte("This small file is in ZIP64 format.\n"),
350 Modified: time.Date(2012, 8, 10, 14, 33, 32, 0, timeZone(-4*time.Hour)),
351 Mode: 0644,
352 },
353 },
354 },
355
356 {
357 Name: "big.zip",
358 Source: returnBigZipBytes,
359 File: []ZipTestFile{
360 {
361 Name: "big.file",
362 Content: nil,
363 Size: 1<<32 - 1,
364 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC),
365 Mode: 0666,
366 },
367 },
368 },
369 {
370 Name: "utf8-7zip.zip",
371 File: []ZipTestFile{
372 {
373 Name: "世界",
374 Content: []byte{},
375 Mode: 0666,
376 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867862500, timeZone(-8*time.Hour)),
377 },
378 },
379 },
380 {
381 Name: "utf8-infozip.zip",
382 File: []ZipTestFile{
383 {
384 Name: "世界",
385 Content: []byte{},
386 Mode: 0644,
387
388
389
390
391 NonUTF8: true,
392 Modified: time.Date(2017, 11, 6, 13, 9, 27, 0, timeZone(-8*time.Hour)),
393 },
394 },
395 },
396 {
397 Name: "utf8-osx.zip",
398 File: []ZipTestFile{
399 {
400 Name: "世界",
401 Content: []byte{},
402 Mode: 0644,
403
404 NonUTF8: true,
405 Modified: time.Date(2017, 11, 6, 13, 9, 27, 0, timeZone(-8*time.Hour)),
406 },
407 },
408 },
409 {
410 Name: "utf8-winrar.zip",
411 File: []ZipTestFile{
412 {
413 Name: "世界",
414 Content: []byte{},
415 Mode: 0666,
416 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867862500, timeZone(-8*time.Hour)),
417 },
418 },
419 },
420 {
421 Name: "utf8-winzip.zip",
422 File: []ZipTestFile{
423 {
424 Name: "世界",
425 Content: []byte{},
426 Mode: 0666,
427 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867000000, timeZone(-8*time.Hour)),
428 },
429 },
430 },
431 {
432 Name: "time-7zip.zip",
433 File: []ZipTestFile{
434 {
435 Name: "test.txt",
436 Content: []byte{},
437 Size: 1<<32 - 1,
438 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244817900, timeZone(-7*time.Hour)),
439 Mode: 0666,
440 },
441 },
442 },
443 {
444 Name: "time-infozip.zip",
445 File: []ZipTestFile{
446 {
447 Name: "test.txt",
448 Content: []byte{},
449 Size: 1<<32 - 1,
450 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)),
451 Mode: 0644,
452 },
453 },
454 },
455 {
456 Name: "time-osx.zip",
457 File: []ZipTestFile{
458 {
459 Name: "test.txt",
460 Content: []byte{},
461 Size: 1<<32 - 1,
462 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)),
463 Mode: 0644,
464 },
465 },
466 },
467 {
468 Name: "time-win7.zip",
469 File: []ZipTestFile{
470 {
471 Name: "test.txt",
472 Content: []byte{},
473 Size: 1<<32 - 1,
474 Modified: time.Date(2017, 10, 31, 21, 11, 58, 0, time.UTC),
475 Mode: 0666,
476 },
477 },
478 },
479 {
480 Name: "time-winrar.zip",
481 File: []ZipTestFile{
482 {
483 Name: "test.txt",
484 Content: []byte{},
485 Size: 1<<32 - 1,
486 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244817900, timeZone(-7*time.Hour)),
487 Mode: 0666,
488 },
489 },
490 },
491 {
492 Name: "time-winzip.zip",
493 File: []ZipTestFile{
494 {
495 Name: "test.txt",
496 Content: []byte{},
497 Size: 1<<32 - 1,
498 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244000000, timeZone(-7*time.Hour)),
499 Mode: 0666,
500 },
501 },
502 },
503 {
504 Name: "time-go.zip",
505 File: []ZipTestFile{
506 {
507 Name: "test.txt",
508 Content: []byte{},
509 Size: 1<<32 - 1,
510 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)),
511 Mode: 0666,
512 },
513 },
514 },
515 {
516 Name: "time-22738.zip",
517 File: []ZipTestFile{
518 {
519 Name: "file",
520 Content: []byte{},
521 Mode: 0666,
522 Modified: time.Date(1999, 12, 31, 19, 0, 0, 0, timeZone(-5*time.Hour)),
523 ModTime: time.Date(1999, 12, 31, 19, 0, 0, 0, time.UTC),
524 },
525 },
526 },
527 {
528 Name: "dupdir.zip",
529 File: []ZipTestFile{
530 {
531 Name: "a/",
532 Content: []byte{},
533 Mode: fs.ModeDir | 0666,
534 Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
535 },
536 {
537 Name: "a/b",
538 Content: []byte{},
539 Mode: 0666,
540 Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
541 },
542 {
543 Name: "a/b/",
544 Content: []byte{},
545 Mode: fs.ModeDir | 0666,
546 Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
547 },
548 {
549 Name: "a/b/c",
550 Content: []byte{},
551 Mode: 0666,
552 Modified: time.Date(2021, 12, 29, 0, 0, 0, 0, timeZone(0)),
553 },
554 },
555 },
556 }
557
558 func TestReader(t *testing.T) {
559 for _, zt := range tests {
560 t.Run(zt.Name, func(t *testing.T) {
561 readTestZip(t, zt)
562 })
563 }
564 }
565
566 func readTestZip(t *testing.T, zt ZipTest) {
567 var z *Reader
568 var err error
569 var raw []byte
570 if zt.Source != nil {
571 rat, size := zt.Source()
572 z, err = NewReader(rat, size)
573 raw = make([]byte, size)
574 if _, err := rat.ReadAt(raw, 0); err != nil {
575 t.Errorf("ReadAt error=%v", err)
576 return
577 }
578 } else {
579 path := filepath.Join("testdata", zt.Name)
580 if zt.Obscured {
581 tf, err := obscuretestdata.DecodeToTempFile(path)
582 if err != nil {
583 t.Errorf("obscuretestdata.DecodeToTempFile(%s): %v", path, err)
584 return
585 }
586 defer os.Remove(tf)
587 path = tf
588 }
589 var rc *ReadCloser
590 rc, err = OpenReader(path)
591 if err == nil {
592 defer rc.Close()
593 z = &rc.Reader
594 }
595 var err2 error
596 raw, err2 = os.ReadFile(path)
597 if err2 != nil {
598 t.Errorf("ReadFile(%s) error=%v", path, err2)
599 return
600 }
601 }
602 if err != zt.Error {
603 t.Errorf("error=%v, want %v", err, zt.Error)
604 return
605 }
606
607
608 if err == ErrFormat {
609 return
610 }
611
612
613
614 if zt.File == nil {
615 return
616 }
617
618 if z.Comment != zt.Comment {
619 t.Errorf("comment=%q, want %q", z.Comment, zt.Comment)
620 }
621 if len(z.File) != len(zt.File) {
622 t.Fatalf("file count=%d, want %d", len(z.File), len(zt.File))
623 }
624
625
626 for i, ft := range zt.File {
627 readTestFile(t, zt, ft, z.File[i], raw)
628 }
629 if t.Failed() {
630 return
631 }
632
633
634 n := 0
635 done := make(chan bool)
636 for i := 0; i < 5; i++ {
637 for j, ft := range zt.File {
638 go func(j int, ft ZipTestFile) {
639 readTestFile(t, zt, ft, z.File[j], raw)
640 done <- true
641 }(j, ft)
642 n++
643 }
644 }
645 for ; n > 0; n-- {
646 <-done
647 }
648 }
649
650 func equalTimeAndZone(t1, t2 time.Time) bool {
651 name1, offset1 := t1.Zone()
652 name2, offset2 := t2.Zone()
653 return t1.Equal(t2) && name1 == name2 && offset1 == offset2
654 }
655
656 func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File, raw []byte) {
657 if f.Name != ft.Name {
658 t.Errorf("name=%q, want %q", f.Name, ft.Name)
659 }
660 if !ft.Modified.IsZero() && !equalTimeAndZone(f.Modified, ft.Modified) {
661 t.Errorf("%s: Modified=%s, want %s", f.Name, f.Modified, ft.Modified)
662 }
663 if !ft.ModTime.IsZero() && !equalTimeAndZone(f.ModTime(), ft.ModTime) {
664 t.Errorf("%s: ModTime=%s, want %s", f.Name, f.ModTime(), ft.ModTime)
665 }
666
667 testFileMode(t, f, ft.Mode)
668
669 size := uint64(f.UncompressedSize)
670 if size == uint32max {
671 size = f.UncompressedSize64
672 } else if size != f.UncompressedSize64 {
673 t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
674 }
675
676
677 rw, err := f.OpenRaw()
678 if err != nil {
679 t.Errorf("%v: OpenRaw error=%v", f.Name, err)
680 return
681 }
682 start, err := f.DataOffset()
683 if err != nil {
684 t.Errorf("%v: DataOffset error=%v", f.Name, err)
685 return
686 }
687 got, err := io.ReadAll(rw)
688 if err != nil {
689 t.Errorf("%v: OpenRaw ReadAll error=%v", f.Name, err)
690 return
691 }
692 end := uint64(start) + f.CompressedSize64
693 want := raw[start:end]
694 if !bytes.Equal(got, want) {
695 t.Logf("got %q", got)
696 t.Logf("want %q", want)
697 t.Errorf("%v: OpenRaw returned unexpected bytes", f.Name)
698 return
699 }
700
701 r, err := f.Open()
702 if err != nil {
703 t.Errorf("%v", err)
704 return
705 }
706
707
708
709
710 if ft.Content == nil && ft.File == "" && ft.Size > 0 {
711 if size != ft.Size {
712 t.Errorf("%v: uncompressed size %#x, want %#x", ft.Name, size, ft.Size)
713 }
714 r.Close()
715 return
716 }
717
718 var b bytes.Buffer
719 _, err = io.Copy(&b, r)
720 if err != ft.ContentErr {
721 t.Errorf("copying contents: %v (want %v)", err, ft.ContentErr)
722 }
723 if err != nil {
724 return
725 }
726 r.Close()
727
728 if g := uint64(b.Len()); g != size {
729 t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size)
730 }
731
732 var c []byte
733 if ft.Content != nil {
734 c = ft.Content
735 } else if c, err = os.ReadFile("testdata/" + ft.File); err != nil {
736 t.Error(err)
737 return
738 }
739
740 if b.Len() != len(c) {
741 t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c))
742 return
743 }
744
745 for i, b := range b.Bytes() {
746 if b != c[i] {
747 t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i])
748 return
749 }
750 }
751 }
752
753 func testFileMode(t *testing.T, f *File, want fs.FileMode) {
754 mode := f.Mode()
755 if want == 0 {
756 t.Errorf("%s mode: got %v, want none", f.Name, mode)
757 } else if mode != want {
758 t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
759 }
760 }
761
762 func TestInvalidFiles(t *testing.T) {
763 const size = 1024 * 70
764 b := make([]byte, size)
765
766
767 _, err := NewReader(bytes.NewReader(b), size)
768 if err != ErrFormat {
769 t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
770 }
771
772
773 sig := make([]byte, 4)
774 binary.LittleEndian.PutUint32(sig, directoryEndSignature)
775 for i := 0; i < size-4; i += 4 {
776 copy(b[i:i+4], sig)
777 }
778 _, err = NewReader(bytes.NewReader(b), size)
779 if err != ErrFormat {
780 t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
781 }
782
783
784 _, err = NewReader(bytes.NewReader([]byte("foobar")), -1)
785 if err == nil {
786 t.Errorf("archive/zip.NewReader: expected error when negative size is passed")
787 }
788 }
789
790 func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
791 data, err := os.ReadFile(filepath.Join("testdata", fileName))
792 if err != nil {
793 panic("Error reading " + fileName + ": " + err.Error())
794 }
795 corrupter(data)
796 return bytes.NewReader(data), int64(len(data))
797 }
798
799 func returnCorruptCRC32Zip() (r io.ReaderAt, size int64) {
800 return messWith("go-with-datadesc-sig.zip", func(b []byte) {
801
802 b[0x2d]++
803 })
804 }
805
806 func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) {
807 return messWith("crc32-not-streamed.zip", func(b []byte) {
808
809
810 b[0x11]++
811 b[0x9d]++
812
813
814
815
816
817
818
819 })
820 }
821
822
823
824 func rZipBytes() []byte {
825 s := `
826 0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4
827 0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f
828 0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00
829 0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00
830 0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00
831 0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00
832 0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8
833 0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f
834 0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e
835 0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb
836 00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff
837 00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42
838 00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14
839 00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21
840 00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb
841 00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff
842 0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a
843 0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3
844 0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06
845 0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00
846 0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf
847 0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06
848 0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01
849 0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89
850 0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00
851 0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a
852 00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00
853 00001b0 00 00 6d 01 00 00 00 00`
854 s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
855 s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
856 b, err := hex.DecodeString(s)
857 if err != nil {
858 panic(err)
859 }
860 return b
861 }
862
863 func returnRecursiveZip() (r io.ReaderAt, size int64) {
864 b := rZipBytes()
865 return bytes.NewReader(b), int64(len(b))
866 }
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934 func biggestZipBytes() []byte {
935 s := `
936 0000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00
937 0000010 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 62 69
938 0000020 67 67 65 72 2e 7a 69 70 ec dc 6b 4c 53 67 18 07
939 0000030 f0 16 c5 ca 65 2e cb b8 94 20 61 1f 44 33 c7 cd
940 0000040 c0 86 4a b5 c0 62 8a 61 05 c6 cd 91 b2 54 8c 1b
941 0000050 63 8b 03 9c 1b 95 52 5a e3 a0 19 6c b2 05 59 44
942 0000060 64 9d 73 83 71 11 46 61 14 b9 1d 14 09 4a c3 60
943 0000070 2e 4c 6e a5 60 45 02 62 81 95 b6 94 9e 9e 77 e7
944 0000080 d0 43 b6 f8 71 df 96 3c e7 a4 69 ce bf cf e9 79
945 0000090 ce ef 79 3f bf f1 31 db b6 bb 31 76 92 e7 f3 07
946 00000a0 8b fc 9c ca cc 08 cc cb cc 5e d2 1c 88 d9 7e bb
947 00000b0 4f bb 3a 3f 75 f1 5d 7f 8f c2 68 67 77 8f 25 ff
948 00000c0 84 e2 93 2d ef a4 95 3d 71 4e 2c b9 b0 87 c3 be
949 00000d0 3d f8 a7 60 24 61 c5 ef ae 9e c8 6c 6d 4e 69 c8
950 00000e0 67 65 34 f8 37 76 2d 76 5c 54 f3 95 65 49 c7 0f
951 00000f0 18 71 4b 7e 5b 6a d1 79 47 61 41 b0 4e 2a 74 45
952 0000100 43 58 12 b2 5a a5 c6 7d 68 55 88 d4 98 75 18 6d
953 0000110 08 d1 1f 8f 5a 9e 96 ee 45 cf a4 84 4e 4b e8 50
954 0000120 a7 13 d9 06 de 52 81 97 36 b2 d7 b8 fc 2b 5f 55
955 0000130 23 1f 32 59 cf 30 27 fb e2 8a b9 de 45 dd 63 9c
956 0000140 4b b5 8b 96 4c 7a 62 62 cc a1 a7 cf fa f1 fe dd
957 0000150 54 62 11 bf 36 78 b3 c7 b1 b5 f2 61 4d 4e dd 66
958 0000160 32 2e e6 70 34 5f f4 c9 e6 6c 43 6f da 6b c6 c3
959 0000170 09 2c ce 09 57 7f d2 7e b4 23 ba 7c 1b 99 bc 22
960 0000180 3e f1 de 91 2f e3 9c 1b 82 cc c2 84 39 aa e6 de
961 0000190 b4 69 fc cc cb 72 a6 61 45 f0 d3 1d 26 19 7c 8d
962 00001a0 29 c8 66 02 be 77 6a f9 3d 34 79 17 19 c8 96 24
963 00001b0 a3 ac e4 dd 3b 1a 8e c6 fe 96 38 6b bf 67 5a 23
964 00001c0 f4 16 f4 e6 8a b4 fc c2 cd bf 95 66 1d bb 35 aa
965 00001d0 92 7d 66 d8 08 8d a5 1f 54 2a af 09 cf 61 ff d2
966 00001e0 85 9d 8f b6 d7 88 07 4a 86 03 db 64 f3 d9 92 73
967 00001f0 df ec a7 fc 23 4c 8d 83 79 63 2a d9 fd 8d b3 c8
968 0000200 8f 7e d4 19 85 e6 8d 1c 76 f0 8b 58 32 fd 9a d6
969 0000210 85 e2 48 ad c3 d5 60 6f 7e 22 dd ef 09 49 7c 7f
970 0000220 3a 45 c3 71 b7 df f3 4c 63 fb b5 d9 31 5f 6e d6
971 0000230 24 1d a4 4a fe 32 a7 5c 16 48 5c 3e 08 6b 8a d3
972 0000240 25 1d a2 12 a5 59 24 ea 20 5f 52 6d ad 94 db 6b
973 0000250 94 b9 5d eb 4b a7 5c 44 bb 1e f2 3c 6b cf 52 c9
974 0000260 e9 e5 ba 06 b9 c4 e5 0a d0 00 0d d0 00 0d d0 00
975 0000270 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d
976 0000280 d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0
977 0000290 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00
978 00002a0 0d d0 00 cd ff 9e 46 86 fa a7 7d 3a 43 d7 8e 10
979 00002b0 52 e9 be e6 6e cf eb 9e 85 4d 65 ce cc 30 c1 44
980 00002c0 c0 4e af bc 9c 6c 4b a0 d7 54 ff 1d d5 5c 89 fb
981 00002d0 b5 34 7e c4 c2 9e f5 a0 f6 5b 7e 6e ca 73 c7 ef
982 00002e0 5d be de f9 e8 81 eb a5 0a a5 63 54 2c d7 1c d1
983 00002f0 89 17 85 f8 16 94 f2 8a b2 a3 f5 b6 6d df 75 cd
984 0000300 90 dd 64 bd 5d 55 4e f2 55 19 1b b7 cc ef 1b ea
985 0000310 2e 05 9c f4 aa 1e a8 cd a6 82 c7 59 0f 5e 9d e0
986 0000320 bb fc 6c d6 99 23 eb 36 ad c6 c5 e1 d8 e1 e2 3e
987 0000330 d9 90 5a f7 91 5d 6f bc 33 6d 98 47 d2 7c 2e 2f
988 0000340 99 a4 25 72 85 49 2c be 0b 5b af 8f e5 6e 81 a6
989 0000350 a3 5a 6f 39 53 3a ab 7a 8b 1e 26 f7 46 6c 7d 26
990 0000360 53 b3 22 31 94 d3 83 f2 18 4d f5 92 33 27 53 97
991 0000370 0f d3 e6 55 9c a6 c5 31 87 6f d3 f3 ae 39 6f 56
992 0000380 10 7b ab 7e d0 b4 ca f2 b8 05 be 3f 0e 6e 5a 75
993 0000390 ab 0c f5 37 0e ba 8e 75 71 7a aa ed 7a dd 6a 63
994 00003a0 be 9b a0 97 27 6a 6f e7 d3 8b c4 7c ec d3 91 56
995 00003b0 d9 ac 5e bf 16 42 2f 00 1f 93 a2 23 87 bd e2 59
996 00003c0 a0 de 1a 66 c8 62 eb 55 8f 91 17 b4 61 42 7a 50
997 00003d0 40 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40
998 00003e0 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40 03
999 00003f0 34 40 03 34 40 03 34 ff 85 86 90 8b ea 67 90 0d
1000 0000400 e1 42 1b d2 61 d6 79 ec fd 3e 44 28 a4 51 6c 5c
1001 0000410 fc d2 72 ca ba 82 18 46 16 61 cd 93 a9 0f d1 24
1002 0000420 17 99 e2 2c 71 16 84 0c c8 7a 13 0f 9a 5e c5 f0
1003 0000430 79 64 e2 12 4d c8 82 a1 81 19 2d aa 44 6d 87 54
1004 0000440 84 71 c1 f6 d4 ca 25 8c 77 b9 08 c7 c8 5e 10 8a
1005 0000450 8f 61 ed 8c ba 30 1f 79 9a c7 60 34 2b b9 8c f8
1006 0000460 18 a6 83 1b e3 9f ad 79 fe fd 1b 8b f1 fc 41 6f
1007 0000470 d4 13 1f e3 b8 83 ba 64 92 e7 eb e4 77 05 8f ba
1008 0000480 fa 3b 00 00 ff ff 50 4b 07 08 a6 18 b1 91 5e 04
1009 0000490 00 00 e4 47 00 00 50 4b 01 02 14 00 14 00 08 00
1010 00004a0 08 00 00 00 00 00 a6 18 b1 91 5e 04 00 00 e4 47
1011 00004b0 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 00 00
1012 00004c0 00 00 00 00 62 69 67 67 65 72 2e 7a 69 70 50 4b
1013 00004d0 05 06 00 00 00 00 01 00 01 00 38 00 00 00 96 04
1014 00004e0 00 00 00 00`
1015 s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
1016 s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
1017 b, err := hex.DecodeString(s)
1018 if err != nil {
1019 panic(err)
1020 }
1021 return b
1022 }
1023
1024 func returnBigZipBytes() (r io.ReaderAt, size int64) {
1025 b := biggestZipBytes()
1026 for i := 0; i < 2; i++ {
1027 r, err := NewReader(bytes.NewReader(b), int64(len(b)))
1028 if err != nil {
1029 panic(err)
1030 }
1031 f, err := r.File[0].Open()
1032 if err != nil {
1033 panic(err)
1034 }
1035 b, err = io.ReadAll(f)
1036 if err != nil {
1037 panic(err)
1038 }
1039 }
1040 return bytes.NewReader(b), int64(len(b))
1041 }
1042
1043 func TestIssue8186(t *testing.T) {
1044
1045 dirEnts := []string{
1046 "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",
1047 "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",
1048 "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",
1049 "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",
1050 "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",
1051 "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",
1052 "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",
1053 "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",
1054 "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",
1055 }
1056 for i, s := range dirEnts {
1057 var f File
1058 err := readDirectoryHeader(&f, strings.NewReader(s))
1059 if err != nil {
1060 t.Errorf("error reading #%d: %v", i, err)
1061 }
1062 }
1063 }
1064
1065
1066 func TestIssue10957(t *testing.T) {
1067 data := []byte("PK\x03\x040000000PK\x01\x0200000" +
1068 "0000000000000000000\x00" +
1069 "\x00\x00\x00\x00\x00000000000000PK\x01" +
1070 "\x020000000000000000000" +
1071 "00000\v\x00\x00\x00\x00\x00000000000" +
1072 "00000000000000PK\x01\x0200" +
1073 "00000000000000000000" +
1074 "00\v\x00\x00\x00\x00\x00000000000000" +
1075 "00000000000PK\x01\x020000<" +
1076 "0\x00\x0000000000000000\v\x00\v" +
1077 "\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
1078 "00000000PK\x01\x0200000000" +
1079 "0000000000000000\v\x00\x00\x00" +
1080 "\x00\x0000PK\x05\x06000000\x05\x00\xfd\x00\x00\x00" +
1081 "\v\x00\x00\x00\x00\x00")
1082 z, err := NewReader(bytes.NewReader(data), int64(len(data)))
1083 if err != nil {
1084 t.Fatal(err)
1085 }
1086 for i, f := range z.File {
1087 r, err := f.Open()
1088 if err != nil {
1089 continue
1090 }
1091 if f.UncompressedSize64 < 1e6 {
1092 n, err := io.Copy(io.Discard, r)
1093 if i == 3 && err != io.ErrUnexpectedEOF {
1094 t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
1095 }
1096 if err == nil && uint64(n) != f.UncompressedSize64 {
1097 t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64)
1098 }
1099 }
1100 r.Close()
1101 }
1102 }
1103
1104
1105 func TestIssue10956(t *testing.T) {
1106 data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" +
1107 "0000PK\x05\x06000000000000" +
1108 "0000\v\x00000\x00\x00\x00\x00\x00\x00\x000")
1109 r, err := NewReader(bytes.NewReader(data), int64(len(data)))
1110 if err == nil {
1111 t.Errorf("got nil error, want ErrFormat")
1112 }
1113 if r != nil {
1114 t.Errorf("got non-nil Reader, want nil")
1115 }
1116 }
1117
1118
1119 func TestIssue11146(t *testing.T) {
1120 data := []byte("PK\x03\x040000000000000000" +
1121 "000000\x01\x00\x00\x000\x01\x00\x00\xff\xff0000" +
1122 "0000000000000000PK\x01\x02" +
1123 "0000\b0\b\x00000000000000" +
1124 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" +
1125 "\x00\x0000\x01\x00\x26\x00\x00\x008\x00\x00\x00\x00\x00")
1126 z, err := NewReader(bytes.NewReader(data), int64(len(data)))
1127 if err != nil {
1128 t.Fatal(err)
1129 }
1130 r, err := z.File[0].Open()
1131 if err != nil {
1132 t.Fatal(err)
1133 }
1134 _, err = io.ReadAll(r)
1135 if err != io.ErrUnexpectedEOF {
1136 t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
1137 }
1138 r.Close()
1139 }
1140
1141
1142 func TestIssue12449(t *testing.T) {
1143 data := []byte{
1144 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
1145 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1147 0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0xca, 0x64,
1148 0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
1149 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1150 0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
1151 0x00, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x0a,
1152 0x50, 0x4b, 0x07, 0x08, 0x1d, 0x88, 0x77, 0xb0,
1153 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1154 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00,
1155 0x08, 0x00, 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46,
1156 0x1d, 0x88, 0x77, 0xb0, 0x07, 0x00, 0x00, 0x00,
1157 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00,
1158 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0xa0, 0x81, 0x00, 0x00, 0x00, 0x00, 0xca, 0x64,
1160 0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
1161 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
1162 0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
1163 0x00, 0x97, 0x2b, 0x49, 0x23, 0x05, 0xc5, 0x0b,
1164 0xa7, 0xd1, 0x52, 0xa2, 0x9c, 0x50, 0x4b, 0x06,
1165 0x07, 0xc8, 0x19, 0xc1, 0xaf, 0x94, 0x9c, 0x61,
1166 0x44, 0xbe, 0x94, 0x19, 0x42, 0x58, 0x12, 0xc6,
1167 0x5b, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00,
1168 0x00, 0x01, 0x00, 0x01, 0x00, 0x69, 0x00, 0x00,
1169 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 }
1171
1172 _, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
1173 if err != nil {
1174 t.Errorf("Error reading the archive: %v", err)
1175 }
1176 }
1177
1178 func TestFS(t *testing.T) {
1179 for _, test := range []struct {
1180 file string
1181 want []string
1182 }{
1183 {
1184 "testdata/unix.zip",
1185 []string{"hello", "dir/bar", "readonly"},
1186 },
1187 {
1188 "testdata/subdir.zip",
1189 []string{"a/b/c"},
1190 },
1191 } {
1192 test := test
1193 t.Run(test.file, func(t *testing.T) {
1194 t.Parallel()
1195 z, err := OpenReader(test.file)
1196 if err != nil {
1197 t.Fatal(err)
1198 }
1199 defer z.Close()
1200 if err := fstest.TestFS(z, test.want...); err != nil {
1201 t.Error(err)
1202 }
1203 })
1204 }
1205 }
1206
1207 func TestFSWalk(t *testing.T) {
1208 for _, test := range []struct {
1209 file string
1210 want []string
1211 wantErr bool
1212 }{
1213 {
1214 file: "testdata/unix.zip",
1215 want: []string{".", "dir", "dir/bar", "dir/empty", "hello", "readonly"},
1216 },
1217 {
1218 file: "testdata/subdir.zip",
1219 want: []string{".", "a", "a/b", "a/b/c"},
1220 },
1221 {
1222 file: "testdata/dupdir.zip",
1223 wantErr: true,
1224 },
1225 } {
1226 test := test
1227 t.Run(test.file, func(t *testing.T) {
1228 t.Parallel()
1229 z, err := OpenReader(test.file)
1230 if err != nil {
1231 t.Fatal(err)
1232 }
1233 var files []string
1234 sawErr := false
1235 err = fs.WalkDir(z, ".", func(path string, d fs.DirEntry, err error) error {
1236 if err != nil {
1237 if !test.wantErr {
1238 t.Errorf("%s: %v", path, err)
1239 }
1240 sawErr = true
1241 return nil
1242 }
1243 files = append(files, path)
1244 return nil
1245 })
1246 if err != nil {
1247 t.Errorf("fs.WalkDir error: %v", err)
1248 }
1249 if test.wantErr && !sawErr {
1250 t.Error("succeeded but want error")
1251 } else if !test.wantErr && sawErr {
1252 t.Error("unexpected error")
1253 }
1254 if test.want != nil && !reflect.DeepEqual(files, test.want) {
1255 t.Errorf("got %v want %v", files, test.want)
1256 }
1257 })
1258 }
1259 }
1260
1261 func TestFSModTime(t *testing.T) {
1262 t.Parallel()
1263 z, err := OpenReader("testdata/subdir.zip")
1264 if err != nil {
1265 t.Fatal(err)
1266 }
1267 defer z.Close()
1268
1269 for _, test := range []struct {
1270 name string
1271 want time.Time
1272 }{
1273 {
1274 "a",
1275 time.Date(2021, 4, 19, 12, 29, 56, 0, timeZone(-7*time.Hour)).UTC(),
1276 },
1277 {
1278 "a/b/c",
1279 time.Date(2021, 4, 19, 12, 29, 59, 0, timeZone(-7*time.Hour)).UTC(),
1280 },
1281 } {
1282 fi, err := fs.Stat(z, test.name)
1283 if err != nil {
1284 t.Errorf("%s: %v", test.name, err)
1285 continue
1286 }
1287 if got := fi.ModTime(); !got.Equal(test.want) {
1288 t.Errorf("%s: got modtime %v, want %v", test.name, got, test.want)
1289 }
1290 }
1291 }
1292
1293 func TestCVE202127919(t *testing.T) {
1294
1295 data := []byte{
1296 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
1297 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
1300 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
1301 0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
1302 0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
1303 0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
1304 0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
1305 0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
1306 0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
1307 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
1308 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
1309 0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
1310 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
1313 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
1314 0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
1315 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
1316 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 }
1318 r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
1319 if err != nil {
1320 t.Fatalf("Error reading the archive: %v", err)
1321 }
1322 _, err = r.Open("test.txt")
1323 if err != nil {
1324 t.Errorf("Error reading file: %v", err)
1325 }
1326 if len(r.File) != 1 {
1327 t.Fatalf("No entries in the file list")
1328 }
1329 if r.File[0].Name != "../test.txt" {
1330 t.Errorf("Unexpected entry name: %s", r.File[0].Name)
1331 }
1332 if _, err := r.File[0].Open(); err != nil {
1333 t.Errorf("Error opening file: %v", err)
1334 }
1335 }
1336
1337 func TestCVE202133196(t *testing.T) {
1338
1339
1340
1341 data := []byte{
1342 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
1343 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
1346 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
1347 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
1348 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
1349 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
1350 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
1351 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
1352 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
1353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
1357 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1358 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1359 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
1360 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
1361 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
1362 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
1363 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
1365 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
1366 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1367 0xff, 0xff, 0xff, 0x00, 0x00,
1368 }
1369 _, err := NewReader(bytes.NewReader(data), int64(len(data)))
1370 if err != ErrFormat {
1371 t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
1372 }
1373
1374
1375
1376 b := bytes.NewBuffer(nil)
1377 w := NewWriter(b)
1378 for i := 0; i < 5; i++ {
1379 _, err := w.Create("")
1380 if err != nil {
1381 t.Fatalf("Writer.Create failed: %s", err)
1382 }
1383 }
1384 if err := w.Close(); err != nil {
1385 t.Fatalf("Writer.Close failed: %s", err)
1386 }
1387 r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
1388 if err != nil {
1389 t.Fatalf("NewReader failed: %s", err)
1390 }
1391 if len(r.File) != 5 {
1392 t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
1393 }
1394 }
1395
1396 func TestCVE202139293(t *testing.T) {
1397
1398
1399
1400 data := []byte{
1401 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
1402 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1403 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
1404 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1405 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1406 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
1407 }
1408 _, err := NewReader(bytes.NewReader(data), int64(len(data)))
1409 if err != ErrFormat {
1410 t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
1411 }
1412 }
1413
1414 func TestCVE202141772(t *testing.T) {
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426 data := []byte{
1427 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x08,
1428 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, 0x00, 0x00,
1429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x50,
1431 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00,
1432 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x50,
1435 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00,
1436 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1438 0x00, 0x01, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x4b,
1439 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
1440 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, 0x4a, 0x0d,
1441 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1442 0x09, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73,
1443 0x74, 0x2e, 0x74, 0x78, 0x74, 0x68, 0x65, 0x6c,
1444 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
1445 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x0a, 0x00,
1446 0x00, 0x08, 0x00, 0x00, 0x06, 0x94, 0x05, 0x53,
1447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1448 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
1450 0xed, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x50,
1451 0x4b, 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00,
1452 0x00, 0x00, 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00,
1453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00,
1455 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1456 0x00, 0x1f, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x0a,
1457 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1458 0x00, 0x18, 0x00, 0x93, 0x98, 0x25, 0x57, 0x25,
1459 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25,
1460 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25,
1461 0xa9, 0xd7, 0x01, 0x50, 0x4b, 0x01, 0x02, 0x3f,
1462 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
1463 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
1464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1465 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x00, 0x20, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00,
1467 0x00, 0x5c, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x93, 0x98,
1469 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98,
1470 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98,
1471 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x50, 0x4b,
1472 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00,
1473 0x00, 0x00, 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11,
1474 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00,
1475 0x00, 0x00, 0x09, 0x00, 0x24, 0x00, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1477 0x5e, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73,
1478 0x74, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0x00, 0x20,
1479 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18,
1480 0x00, 0xa9, 0x80, 0x51, 0x01, 0x26, 0xa9, 0xd7,
1481 0x01, 0x31, 0xd1, 0x57, 0x01, 0x26, 0xa9, 0xd7,
1482 0x01, 0xdf, 0x48, 0x85, 0xf9, 0x25, 0xa9, 0xd7,
1483 0x01, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00,
1484 0x00, 0x04, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00,
1485 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
1486 }
1487 r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
1488 if err != nil {
1489 t.Fatalf("Error reading the archive: %v", err)
1490 }
1491 entryNames := []string{`/`, `//`, `\`, `/test.txt`}
1492 var names []string
1493 for _, f := range r.File {
1494 names = append(names, f.Name)
1495 if _, err := f.Open(); err != nil {
1496 t.Errorf("Error opening %q: %v", f.Name, err)
1497 }
1498 if _, err := r.Open(f.Name); err == nil {
1499 t.Errorf("Opening %q with fs.FS API succeeded", f.Name)
1500 }
1501 }
1502 if !reflect.DeepEqual(names, entryNames) {
1503 t.Errorf("Unexpected file entries: %q", names)
1504 }
1505 if _, err := r.Open(""); err == nil {
1506 t.Errorf("Opening %q with fs.FS API succeeded", "")
1507 }
1508 if _, err := r.Open("test.txt"); err != nil {
1509 t.Errorf("Error opening %q with fs.FS API: %v", "test.txt", err)
1510 }
1511 dirEntries, err := fs.ReadDir(r, ".")
1512 if err != nil {
1513 t.Fatalf("Error reading the root directory: %v", err)
1514 }
1515 if len(dirEntries) != 1 || dirEntries[0].Name() != "test.txt" {
1516 t.Errorf("Unexpected directory entries")
1517 for _, dirEntry := range dirEntries {
1518 _, err := r.Open(dirEntry.Name())
1519 t.Logf("%q (Open error: %v)", dirEntry.Name(), err)
1520 }
1521 t.FailNow()
1522 }
1523 info, err := dirEntries[0].Info()
1524 if err != nil {
1525 t.Fatalf("Error reading info entry: %v", err)
1526 }
1527 if name := info.Name(); name != "test.txt" {
1528 t.Errorf("Inconsistent name in info entry: %v", name)
1529 }
1530 }
1531
1532 func TestUnderSize(t *testing.T) {
1533 z, err := OpenReader("testdata/readme.zip")
1534 if err != nil {
1535 t.Fatal(err)
1536 }
1537 defer z.Close()
1538
1539 for _, f := range z.File {
1540 f.UncompressedSize64 = 1
1541 }
1542
1543 for _, f := range z.File {
1544 t.Run(f.Name, func(t *testing.T) {
1545 rd, err := f.Open()
1546 if err != nil {
1547 t.Fatal(err)
1548 }
1549 defer rd.Close()
1550
1551 _, err = io.Copy(io.Discard, rd)
1552 if err != ErrFormat {
1553 t.Fatalf("Error mismatch\n\tGot: %v\n\tWant: %v", err, ErrFormat)
1554 }
1555 })
1556 }
1557 }
1558
View as plain text