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