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 test := test
1217 t.Run(test.file, func(t *testing.T) {
1218 t.Parallel()
1219 z, err := OpenReader(test.file)
1220 if err != nil {
1221 t.Fatal(err)
1222 }
1223 defer z.Close()
1224 if err := fstest.TestFS(z, test.want...); err != nil {
1225 t.Error(err)
1226 }
1227 })
1228 }
1229 }
1230
1231 func TestFSWalk(t *testing.T) {
1232 for _, test := range []struct {
1233 file string
1234 want []string
1235 wantErr bool
1236 }{
1237 {
1238 file: "testdata/unix.zip",
1239 want: []string{".", "dir", "dir/bar", "dir/empty", "hello", "readonly"},
1240 },
1241 {
1242 file: "testdata/subdir.zip",
1243 want: []string{".", "a", "a/b", "a/b/c"},
1244 },
1245 {
1246 file: "testdata/dupdir.zip",
1247 wantErr: true,
1248 },
1249 } {
1250 test := test
1251 t.Run(test.file, func(t *testing.T) {
1252 t.Parallel()
1253 z, err := OpenReader(test.file)
1254 if err != nil {
1255 t.Fatal(err)
1256 }
1257 var files []string
1258 sawErr := false
1259 err = fs.WalkDir(z, ".", func(path string, d fs.DirEntry, err error) error {
1260 if err != nil {
1261 if !test.wantErr {
1262 t.Errorf("%s: %v", path, err)
1263 }
1264 sawErr = true
1265 return nil
1266 }
1267 files = append(files, path)
1268 return nil
1269 })
1270 if err != nil {
1271 t.Errorf("fs.WalkDir error: %v", err)
1272 }
1273 if test.wantErr && !sawErr {
1274 t.Error("succeeded but want error")
1275 } else if !test.wantErr && sawErr {
1276 t.Error("unexpected error")
1277 }
1278 if test.want != nil && !slices.Equal(files, test.want) {
1279 t.Errorf("got %v want %v", files, test.want)
1280 }
1281 })
1282 }
1283 }
1284
1285 func TestFSWalkBadFile(t *testing.T) {
1286 t.Parallel()
1287
1288 var buf bytes.Buffer
1289 zw := NewWriter(&buf)
1290 hdr := &FileHeader{Name: "."}
1291 hdr.SetMode(fs.ModeDir | 0o755)
1292 w, err := zw.CreateHeader(hdr)
1293 if err != nil {
1294 t.Fatalf("create zip header: %v", err)
1295 }
1296 _, err = w.Write([]byte("some data"))
1297 if err != nil {
1298 t.Fatalf("write zip contents: %v", err)
1299
1300 }
1301 err = zw.Close()
1302 if err != nil {
1303 t.Fatalf("close zip writer: %v", err)
1304
1305 }
1306
1307 zr, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
1308 if err != nil {
1309 t.Fatalf("create zip reader: %v", err)
1310
1311 }
1312 var count int
1313 var errRepeat = errors.New("repeated call to path")
1314 err = fs.WalkDir(zr, ".", func(p string, d fs.DirEntry, err error) error {
1315 count++
1316 if count > 2 {
1317 return errRepeat
1318 }
1319 return err
1320 })
1321 if err == nil {
1322 t.Fatalf("expected error from invalid file name")
1323 } else if errors.Is(err, errRepeat) {
1324 t.Fatal(err)
1325 }
1326 }
1327
1328 func TestFSModTime(t *testing.T) {
1329 t.Parallel()
1330 z, err := OpenReader("testdata/subdir.zip")
1331 if err != nil {
1332 t.Fatal(err)
1333 }
1334 defer z.Close()
1335
1336 for _, test := range []struct {
1337 name string
1338 want time.Time
1339 }{
1340 {
1341 "a",
1342 time.Date(2021, 4, 19, 12, 29, 56, 0, timeZone(-7*time.Hour)).UTC(),
1343 },
1344 {
1345 "a/b/c",
1346 time.Date(2021, 4, 19, 12, 29, 59, 0, timeZone(-7*time.Hour)).UTC(),
1347 },
1348 } {
1349 fi, err := fs.Stat(z, test.name)
1350 if err != nil {
1351 t.Errorf("%s: %v", test.name, err)
1352 continue
1353 }
1354 if got := fi.ModTime(); !got.Equal(test.want) {
1355 t.Errorf("%s: got modtime %v, want %v", test.name, got, test.want)
1356 }
1357 }
1358 }
1359
1360 func TestCVE202127919(t *testing.T) {
1361 t.Setenv("GODEBUG", "zipinsecurepath=0")
1362
1363 data := []byte{
1364 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
1365 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
1368 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
1369 0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
1370 0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
1371 0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
1372 0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
1373 0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
1374 0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
1375 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
1376 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
1378 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
1381 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
1382 0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
1383 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
1384 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 }
1386 r, err := NewReader(bytes.NewReader(data), int64(len(data)))
1387 if err != ErrInsecurePath {
1388 t.Fatalf("Error reading the archive: %v", err)
1389 }
1390 _, err = r.Open("test.txt")
1391 if err != nil {
1392 t.Errorf("Error reading file: %v", err)
1393 }
1394 if len(r.File) != 1 {
1395 t.Fatalf("No entries in the file list")
1396 }
1397 if r.File[0].Name != "../test.txt" {
1398 t.Errorf("Unexpected entry name: %s", r.File[0].Name)
1399 }
1400 if _, err := r.File[0].Open(); err != nil {
1401 t.Errorf("Error opening file: %v", err)
1402 }
1403 }
1404
1405 func TestOpenReaderInsecurePath(t *testing.T) {
1406 t.Setenv("GODEBUG", "zipinsecurepath=0")
1407
1408 data := []byte{
1409 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
1410 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1412 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
1413 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
1414 0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
1415 0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
1416 0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
1417 0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
1418 0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
1419 0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
1420 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
1421 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
1422 0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
1423 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
1424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
1426 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
1427 0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
1428 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
1429 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 }
1431
1432
1433 name := filepath.Join(t.TempDir(), "test.zip")
1434 err := os.WriteFile(name, data, 0644)
1435 if err != nil {
1436 t.Fatalf("Unable to write out the bugos zip entry")
1437 }
1438 r, err := OpenReader(name)
1439 if r != nil {
1440 defer r.Close()
1441 }
1442
1443 if err != ErrInsecurePath {
1444 t.Fatalf("Error reading the archive, we expected ErrInsecurePath but got: %v", err)
1445 }
1446 _, err = r.Open("test.txt")
1447 if err != nil {
1448 t.Errorf("Error reading file: %v", err)
1449 }
1450 if len(r.File) != 1 {
1451 t.Fatalf("No entries in the file list")
1452 }
1453 if r.File[0].Name != "../test.txt" {
1454 t.Errorf("Unexpected entry name: %s", r.File[0].Name)
1455 }
1456 if _, err := r.File[0].Open(); err != nil {
1457 t.Errorf("Error opening file: %v", err)
1458 }
1459 }
1460
1461 func TestCVE202133196(t *testing.T) {
1462
1463
1464
1465 data := []byte{
1466 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
1467 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
1470 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
1471 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
1472 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
1473 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
1474 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
1476 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
1477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1479 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
1480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
1481 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1482 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
1484 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
1485 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
1487 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
1488 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
1489 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
1490 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1491 0xff, 0xff, 0xff, 0x00, 0x00,
1492 }
1493 _, err := NewReader(bytes.NewReader(data), int64(len(data)))
1494 if err != ErrFormat {
1495 t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
1496 }
1497
1498
1499
1500 b := bytes.NewBuffer(nil)
1501 w := NewWriter(b)
1502 for i := 0; i < 5; i++ {
1503 _, err := w.Create("")
1504 if err != nil {
1505 t.Fatalf("Writer.Create failed: %s", err)
1506 }
1507 }
1508 if err := w.Close(); err != nil {
1509 t.Fatalf("Writer.Close failed: %s", err)
1510 }
1511 r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
1512 if err != nil {
1513 t.Fatalf("NewReader failed: %s", err)
1514 }
1515 if len(r.File) != 5 {
1516 t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
1517 }
1518 }
1519
1520 func TestCVE202139293(t *testing.T) {
1521
1522
1523
1524 data := []byte{
1525 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 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, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
1528 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1529 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1530 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
1531 }
1532 _, err := NewReader(bytes.NewReader(data), int64(len(data)))
1533 if err != ErrFormat {
1534 t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
1535 }
1536 }
1537
1538 func TestCVE202141772(t *testing.T) {
1539 t.Setenv("GODEBUG", "zipinsecurepath=0")
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551 data := []byte{
1552 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x08,
1553 0x00, 0x00, 0x06, 0x94, 0x05, 0x53, 0x00, 0x00,
1554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1555 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x50,
1556 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00,
1557 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00,
1558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1559 0x00, 0x02, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x50,
1560 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00,
1561 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00,
1562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1563 0x00, 0x01, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x4b,
1564 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
1565 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11, 0x4a, 0x0d,
1566 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1567 0x09, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73,
1568 0x74, 0x2e, 0x74, 0x78, 0x74, 0x68, 0x65, 0x6c,
1569 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
1570 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x0a, 0x00,
1571 0x00, 0x08, 0x00, 0x00, 0x06, 0x94, 0x05, 0x53,
1572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
1575 0xed, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x50,
1576 0x4b, 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x78, 0x67, 0x2e, 0x53, 0x00,
1578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1579 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00,
1580 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1581 0x00, 0x1f, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x0a,
1582 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1583 0x00, 0x18, 0x00, 0x93, 0x98, 0x25, 0x57, 0x25,
1584 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25,
1585 0xa9, 0xd7, 0x01, 0x93, 0x98, 0x25, 0x57, 0x25,
1586 0xa9, 0xd7, 0x01, 0x50, 0x4b, 0x01, 0x02, 0x3f,
1587 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
1588 0x67, 0x2e, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
1589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1590 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1591 0x00, 0x20, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00,
1592 0x00, 0x5c, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00,
1593 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x93, 0x98,
1594 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98,
1595 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x93, 0x98,
1596 0x25, 0x57, 0x25, 0xa9, 0xd7, 0x01, 0x50, 0x4b,
1597 0x01, 0x02, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00,
1598 0x00, 0x00, 0x91, 0x68, 0x2e, 0x53, 0x85, 0x11,
1599 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00,
1600 0x00, 0x00, 0x09, 0x00, 0x24, 0x00, 0x00, 0x00,
1601 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1602 0x5e, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x65, 0x73,
1603 0x74, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0x00, 0x20,
1604 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18,
1605 0x00, 0xa9, 0x80, 0x51, 0x01, 0x26, 0xa9, 0xd7,
1606 0x01, 0x31, 0xd1, 0x57, 0x01, 0x26, 0xa9, 0xd7,
1607 0x01, 0xdf, 0x48, 0x85, 0xf9, 0x25, 0xa9, 0xd7,
1608 0x01, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00,
1609 0x00, 0x04, 0x00, 0x04, 0x00, 0x31, 0x01, 0x00,
1610 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
1611 }
1612 r, err := NewReader(bytes.NewReader(data), int64(len(data)))
1613 if err != ErrInsecurePath {
1614 t.Fatalf("Error reading the archive: %v", err)
1615 }
1616 entryNames := []string{`/`, `//`, `\`, `/test.txt`}
1617 var names []string
1618 for _, f := range r.File {
1619 names = append(names, f.Name)
1620 if _, err := f.Open(); err != nil {
1621 t.Errorf("Error opening %q: %v", f.Name, err)
1622 }
1623 if _, err := r.Open(f.Name); err == nil {
1624 t.Errorf("Opening %q with fs.FS API succeeded", f.Name)
1625 }
1626 }
1627 if !slices.Equal(names, entryNames) {
1628 t.Errorf("Unexpected file entries: %q", names)
1629 }
1630 if _, err := r.Open(""); err == nil {
1631 t.Errorf("Opening %q with fs.FS API succeeded", "")
1632 }
1633 if _, err := r.Open("test.txt"); err != nil {
1634 t.Errorf("Error opening %q with fs.FS API: %v", "test.txt", err)
1635 }
1636 dirEntries, err := fs.ReadDir(r, ".")
1637 if err != nil {
1638 t.Fatalf("Error reading the root directory: %v", err)
1639 }
1640 if len(dirEntries) != 1 || dirEntries[0].Name() != "test.txt" {
1641 t.Errorf("Unexpected directory entries")
1642 for _, dirEntry := range dirEntries {
1643 _, err := r.Open(dirEntry.Name())
1644 t.Logf("%q (Open error: %v)", dirEntry.Name(), err)
1645 }
1646 t.FailNow()
1647 }
1648 info, err := dirEntries[0].Info()
1649 if err != nil {
1650 t.Fatalf("Error reading info entry: %v", err)
1651 }
1652 if name := info.Name(); name != "test.txt" {
1653 t.Errorf("Inconsistent name in info entry: %v", name)
1654 }
1655 }
1656
1657 func TestUnderSize(t *testing.T) {
1658 z, err := OpenReader("testdata/readme.zip")
1659 if err != nil {
1660 t.Fatal(err)
1661 }
1662 defer z.Close()
1663
1664 for _, f := range z.File {
1665 f.UncompressedSize64 = 1
1666 }
1667
1668 for _, f := range z.File {
1669 t.Run(f.Name, func(t *testing.T) {
1670 rd, err := f.Open()
1671 if err != nil {
1672 t.Fatal(err)
1673 }
1674 defer rd.Close()
1675
1676 _, err = io.Copy(io.Discard, rd)
1677 if err != ErrFormat {
1678 t.Fatalf("Error mismatch\n\tGot: %v\n\tWant: %v", err, ErrFormat)
1679 }
1680 })
1681 }
1682 }
1683
1684 func TestIssue54801(t *testing.T) {
1685 for _, input := range []string{"testdata/readme.zip", "testdata/dd.zip"} {
1686 z, err := OpenReader(input)
1687 if err != nil {
1688 t.Fatal(err)
1689 }
1690 defer z.Close()
1691
1692 for _, f := range z.File {
1693
1694 f.Name += "/"
1695
1696 t.Run(f.Name, func(t *testing.T) {
1697 t.Logf("CompressedSize64: %d, Flags: %#x", f.CompressedSize64, f.Flags)
1698
1699 rd, err := f.Open()
1700 if err != nil {
1701 t.Fatal(err)
1702 }
1703 defer rd.Close()
1704
1705 n, got := io.Copy(io.Discard, rd)
1706 if n != 0 || got != ErrFormat {
1707 t.Fatalf("Error mismatch, got: %d, %v, want: %v", n, got, ErrFormat)
1708 }
1709 })
1710 }
1711 }
1712 }
1713
1714 func TestInsecurePaths(t *testing.T) {
1715 t.Setenv("GODEBUG", "zipinsecurepath=0")
1716 for _, path := range []string{
1717 "../foo",
1718 "/foo",
1719 "a/b/../../../c",
1720 `a\b`,
1721 } {
1722 var buf bytes.Buffer
1723 zw := NewWriter(&buf)
1724 _, err := zw.Create(path)
1725 if err != nil {
1726 t.Errorf("zw.Create(%q) = %v", path, err)
1727 continue
1728 }
1729 zw.Close()
1730
1731 zr, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
1732 if err != ErrInsecurePath {
1733 t.Errorf("NewReader for archive with file %q: got err %v, want ErrInsecurePath", path, err)
1734 continue
1735 }
1736 var gotPaths []string
1737 for _, f := range zr.File {
1738 gotPaths = append(gotPaths, f.Name)
1739 }
1740 if !slices.Equal(gotPaths, []string{path}) {
1741 t.Errorf("NewReader for archive with file %q: got files %q", path, gotPaths)
1742 continue
1743 }
1744 }
1745 }
1746
1747 func TestDisableInsecurePathCheck(t *testing.T) {
1748 t.Setenv("GODEBUG", "zipinsecurepath=1")
1749 var buf bytes.Buffer
1750 zw := NewWriter(&buf)
1751 const name = "/foo"
1752 _, err := zw.Create(name)
1753 if err != nil {
1754 t.Fatalf("zw.Create(%q) = %v", name, err)
1755 }
1756 zw.Close()
1757 zr, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
1758 if err != nil {
1759 t.Fatalf("NewReader with zipinsecurepath=1: got err %v, want nil", err)
1760 }
1761 var gotPaths []string
1762 for _, f := range zr.File {
1763 gotPaths = append(gotPaths, f.Name)
1764 }
1765 if want := []string{name}; !slices.Equal(gotPaths, want) {
1766 t.Errorf("NewReader with zipinsecurepath=1: got files %q, want %q", gotPaths, want)
1767 }
1768 }
1769
1770 func TestCompressedDirectory(t *testing.T) {
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780 data := []byte{
1781 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
1782 0x08, 0x00, 0x49, 0x86, 0x81, 0x55, 0x00, 0x00,
1783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1784 0x00, 0x00, 0x09, 0x00, 0x04, 0x00, 0x4d, 0x45,
1785 0x54, 0x41, 0x2d, 0x49, 0x4e, 0x46, 0x2f, 0xfe,
1786 0xca, 0x00, 0x00, 0x03, 0x00, 0x50, 0x4b, 0x07,
1787 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
1788 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x03,
1789 0x04, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x49,
1790 0x86, 0x81, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
1791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
1792 0x00, 0x00, 0x00, 0x4d, 0x45, 0x54, 0x41, 0x2d,
1793 0x49, 0x4e, 0x46, 0x2f, 0x4d, 0x41, 0x4e, 0x49,
1794 0x46, 0x45, 0x53, 0x54, 0x2e, 0x4d, 0x46, 0xf3,
1795 0x4d, 0xcc, 0xcb, 0x4c, 0x4b, 0x2d, 0x2e, 0xd1,
1796 0x0d, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xb3,
1797 0x52, 0x30, 0xd4, 0x33, 0xe0, 0xe5, 0x72, 0x2e,
1798 0x4a, 0x4d, 0x2c, 0x49, 0x4d, 0xd1, 0x75, 0xaa,
1799 0x04, 0x0a, 0x00, 0x45, 0xf4, 0x0c, 0x8d, 0x15,
1800 0x34, 0xdc, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0x15,
1801 0x3c, 0xf3, 0x92, 0xf5, 0x34, 0x79, 0xb9, 0x78,
1802 0xb9, 0x00, 0x50, 0x4b, 0x07, 0x08, 0x93, 0x7e,
1803 0x93, 0xaf, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00,
1804 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
1805 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x49, 0x86,
1806 0x81, 0x55, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
1807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
1808 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810 0x4d, 0x45, 0x54, 0x41, 0x2d, 0x49, 0x4e, 0x46,
1811 0x2f, 0xfe, 0xca, 0x00, 0x00, 0x50, 0x4b, 0x01,
1812 0x02, 0x14, 0x00, 0x14, 0x00, 0x08, 0x08, 0x08,
1813 0x00, 0x49, 0x86, 0x81, 0x55, 0x93, 0x7e, 0x93,
1814 0xaf, 0x3b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
1815 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d,
1817 0x00, 0x00, 0x00, 0x4d, 0x45, 0x54, 0x41, 0x2d,
1818 0x49, 0x4e, 0x46, 0x2f, 0x4d, 0x41, 0x4e, 0x49,
1819 0x46, 0x45, 0x53, 0x54, 0x2e, 0x4d, 0x46, 0x50,
1820 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02,
1821 0x00, 0x02, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xba,
1822 0x00, 0x00, 0x00, 0x00, 0x00,
1823 }
1824 r, err := NewReader(bytes.NewReader(data), int64(len(data)))
1825 if err != nil {
1826 t.Fatalf("unexpected error: %v", err)
1827 }
1828 for _, f := range r.File {
1829 r, err := f.Open()
1830 if err != nil {
1831 t.Fatalf("unexpected error: %v", err)
1832 }
1833 if _, err := io.Copy(io.Discard, r); err != nil {
1834 t.Fatalf("unexpected error: %v", err)
1835 }
1836 }
1837 }
1838
1839 func TestBaseOffsetPlusOverflow(t *testing.T) {
1840
1841 data := []byte{
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 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1846 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1847 0xff, 0xff, 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, 0x20, 0x20, 0x20, 0x20, 0x20,
1854 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1855 0x20, 0x20, 0x20, 0x50, 0x4b, 0x06, 0x06, 0x20,
1856 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1857 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1858 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1859 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1860 0x20, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x00,
1861 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00,
1862 0x00, 0x00, 0x80, 0x50, 0x4b, 0x06, 0x07, 0x00,
1863 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
1864 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
1865 0x4b, 0x05, 0x06, 0x20, 0x20, 0x20, 0x20, 0xff,
1866 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1867 0xff, 0xff, 0xff, 0x20, 0x00,
1868 }
1869 defer func() {
1870 if r := recover(); r != nil {
1871 t.Fatalf("NewReader panicked: %s", r)
1872 }
1873 }()
1874
1875
1876
1877 NewReader(bytes.NewReader(data), int64(len(data))+1875)
1878 }
1879
View as plain text