github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/archive/zip/reader_test.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package zip 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "encoding/hex" 11 "internal/obscuretestdata" 12 "io" 13 "io/ioutil" 14 "os" 15 "path/filepath" 16 "regexp" 17 "strings" 18 "testing" 19 "time" 20 ) 21 22 type ZipTest struct { 23 Name string 24 Source func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/<Name> file 25 Comment string 26 File []ZipTestFile 27 Obscured bool // needed for Apple notarization (golang.org/issue/34986) 28 Error error // the error that Opening this file should return 29 } 30 31 type ZipTestFile struct { 32 Name string 33 Mode os.FileMode 34 NonUTF8 bool 35 ModTime time.Time 36 Modified time.Time 37 38 // Information describing expected zip file content. 39 // First, reading the entire content should produce the error ContentErr. 40 // Second, if ContentErr==nil, the content should match Content. 41 // If content is large, an alternative to setting Content is to set File, 42 // which names a file in the testdata/ directory containing the 43 // uncompressed expected content. 44 // If content is very large, an alternative to setting Content or File 45 // is to set Size, which will then be checked against the header-reported size 46 // but will bypass the decompressing of the actual data. 47 // This last option is used for testing very large (multi-GB) compressed files. 48 ContentErr error 49 Content []byte 50 File string 51 Size uint64 52 } 53 54 var tests = []ZipTest{ 55 { 56 Name: "test.zip", 57 Comment: "This is a zipfile comment.", 58 File: []ZipTestFile{ 59 { 60 Name: "test.txt", 61 Content: []byte("This is a test text file.\n"), 62 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)), 63 Mode: 0644, 64 }, 65 { 66 Name: "gophercolor16x16.png", 67 File: "gophercolor16x16.png", 68 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)), 69 Mode: 0644, 70 }, 71 }, 72 }, 73 { 74 Name: "test-trailing-junk.zip", 75 Comment: "This is a zipfile comment.", 76 File: []ZipTestFile{ 77 { 78 Name: "test.txt", 79 Content: []byte("This is a test text file.\n"), 80 Modified: time.Date(2010, 9, 5, 12, 12, 1, 0, timeZone(+10*time.Hour)), 81 Mode: 0644, 82 }, 83 { 84 Name: "gophercolor16x16.png", 85 File: "gophercolor16x16.png", 86 Modified: time.Date(2010, 9, 5, 15, 52, 58, 0, timeZone(+10*time.Hour)), 87 Mode: 0644, 88 }, 89 }, 90 }, 91 { 92 Name: "r.zip", 93 Source: returnRecursiveZip, 94 File: []ZipTestFile{ 95 { 96 Name: "r/r.zip", 97 Content: rZipBytes(), 98 Modified: time.Date(2010, 3, 4, 0, 24, 16, 0, time.UTC), 99 Mode: 0666, 100 }, 101 }, 102 }, 103 { 104 Name: "symlink.zip", 105 File: []ZipTestFile{ 106 { 107 Name: "symlink", 108 Content: []byte("../target"), 109 Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)), 110 Mode: 0777 | os.ModeSymlink, 111 }, 112 }, 113 }, 114 { 115 Name: "readme.zip", 116 }, 117 { 118 Name: "readme.notzip", 119 Error: ErrFormat, 120 }, 121 { 122 Name: "dd.zip", 123 File: []ZipTestFile{ 124 { 125 Name: "filename", 126 Content: []byte("This is a test textfile.\n"), 127 Modified: time.Date(2011, 2, 2, 13, 6, 20, 0, time.UTC), 128 Mode: 0666, 129 }, 130 }, 131 }, 132 { 133 // created in windows XP file manager. 134 Name: "winxp.zip", 135 File: []ZipTestFile{ 136 { 137 Name: "hello", 138 Content: []byte("world \r\n"), 139 Modified: time.Date(2011, 12, 8, 10, 4, 24, 0, time.UTC), 140 Mode: 0666, 141 }, 142 { 143 Name: "dir/bar", 144 Content: []byte("foo \r\n"), 145 Modified: time.Date(2011, 12, 8, 10, 4, 50, 0, time.UTC), 146 Mode: 0666, 147 }, 148 { 149 Name: "dir/empty/", 150 Content: []byte{}, 151 Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC), 152 Mode: os.ModeDir | 0777, 153 }, 154 { 155 Name: "readonly", 156 Content: []byte("important \r\n"), 157 Modified: time.Date(2011, 12, 8, 10, 6, 8, 0, time.UTC), 158 Mode: 0444, 159 }, 160 }, 161 }, 162 { 163 // created by Zip 3.0 under Linux 164 Name: "unix.zip", 165 File: []ZipTestFile{ 166 { 167 Name: "hello", 168 Content: []byte("world \r\n"), 169 Modified: time.Date(2011, 12, 8, 10, 4, 24, 0, timeZone(0)), 170 Mode: 0666, 171 }, 172 { 173 Name: "dir/bar", 174 Content: []byte("foo \r\n"), 175 Modified: time.Date(2011, 12, 8, 10, 4, 50, 0, timeZone(0)), 176 Mode: 0666, 177 }, 178 { 179 Name: "dir/empty/", 180 Content: []byte{}, 181 Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)), 182 Mode: os.ModeDir | 0777, 183 }, 184 { 185 Name: "readonly", 186 Content: []byte("important \r\n"), 187 Modified: time.Date(2011, 12, 8, 10, 6, 8, 0, timeZone(0)), 188 Mode: 0444, 189 }, 190 }, 191 }, 192 { 193 // created by Go, before we wrote the "optional" data 194 // descriptor signatures (which are required by macOS). 195 // Use obscured file to avoid Apple’s notarization service 196 // rejecting the toolchain due to an inability to unzip this archive. 197 // See golang.org/issue/34986 198 Name: "go-no-datadesc-sig.zip.base64", 199 Obscured: true, 200 File: []ZipTestFile{ 201 { 202 Name: "foo.txt", 203 Content: []byte("foo\n"), 204 Modified: time.Date(2012, 3, 8, 16, 59, 10, 0, timeZone(-8*time.Hour)), 205 Mode: 0644, 206 }, 207 { 208 Name: "bar.txt", 209 Content: []byte("bar\n"), 210 Modified: time.Date(2012, 3, 8, 16, 59, 12, 0, timeZone(-8*time.Hour)), 211 Mode: 0644, 212 }, 213 }, 214 }, 215 { 216 // created by Go, after we wrote the "optional" data 217 // descriptor signatures (which are required by macOS) 218 Name: "go-with-datadesc-sig.zip", 219 File: []ZipTestFile{ 220 { 221 Name: "foo.txt", 222 Content: []byte("foo\n"), 223 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC), 224 Mode: 0666, 225 }, 226 { 227 Name: "bar.txt", 228 Content: []byte("bar\n"), 229 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC), 230 Mode: 0666, 231 }, 232 }, 233 }, 234 { 235 Name: "Bad-CRC32-in-data-descriptor", 236 Source: returnCorruptCRC32Zip, 237 File: []ZipTestFile{ 238 { 239 Name: "foo.txt", 240 Content: []byte("foo\n"), 241 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC), 242 Mode: 0666, 243 ContentErr: ErrChecksum, 244 }, 245 { 246 Name: "bar.txt", 247 Content: []byte("bar\n"), 248 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC), 249 Mode: 0666, 250 }, 251 }, 252 }, 253 // Tests that we verify (and accept valid) crc32s on files 254 // with crc32s in their file header (not in data descriptors) 255 { 256 Name: "crc32-not-streamed.zip", 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 // Tests that we verify (and reject invalid) crc32s on files 273 // with crc32s in their file header (not in data descriptors) 274 { 275 Name: "crc32-not-streamed.zip", 276 Source: returnCorruptNotStreamedZip, 277 File: []ZipTestFile{ 278 { 279 Name: "foo.txt", 280 Content: []byte("foo\n"), 281 Modified: time.Date(2012, 3, 8, 16, 59, 10, 0, timeZone(-8*time.Hour)), 282 Mode: 0644, 283 ContentErr: ErrChecksum, 284 }, 285 { 286 Name: "bar.txt", 287 Content: []byte("bar\n"), 288 Modified: time.Date(2012, 3, 8, 16, 59, 12, 0, timeZone(-8*time.Hour)), 289 Mode: 0644, 290 }, 291 }, 292 }, 293 { 294 Name: "zip64.zip", 295 File: []ZipTestFile{ 296 { 297 Name: "README", 298 Content: []byte("This small file is in ZIP64 format.\n"), 299 Modified: time.Date(2012, 8, 10, 14, 33, 32, 0, time.UTC), 300 Mode: 0644, 301 }, 302 }, 303 }, 304 // Another zip64 file with different Extras fields. (golang.org/issue/7069) 305 { 306 Name: "zip64-2.zip", 307 File: []ZipTestFile{ 308 { 309 Name: "README", 310 Content: []byte("This small file is in ZIP64 format.\n"), 311 Modified: time.Date(2012, 8, 10, 14, 33, 32, 0, timeZone(-4*time.Hour)), 312 Mode: 0644, 313 }, 314 }, 315 }, 316 // Largest possible non-zip64 file, with no zip64 header. 317 { 318 Name: "big.zip", 319 Source: returnBigZipBytes, 320 File: []ZipTestFile{ 321 { 322 Name: "big.file", 323 Content: nil, 324 Size: 1<<32 - 1, 325 Modified: time.Date(1979, 11, 30, 0, 0, 0, 0, time.UTC), 326 Mode: 0666, 327 }, 328 }, 329 }, 330 { 331 Name: "utf8-7zip.zip", 332 File: []ZipTestFile{ 333 { 334 Name: "世界", 335 Content: []byte{}, 336 Mode: 0666, 337 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867862500, timeZone(-8*time.Hour)), 338 }, 339 }, 340 }, 341 { 342 Name: "utf8-infozip.zip", 343 File: []ZipTestFile{ 344 { 345 Name: "世界", 346 Content: []byte{}, 347 Mode: 0644, 348 // Name is valid UTF-8, but format does not have UTF-8 flag set. 349 // We don't do UTF-8 detection for multi-byte runes due to 350 // false-positives with other encodings (e.g., Shift-JIS). 351 // Format says encoding is not UTF-8, so we trust it. 352 NonUTF8: true, 353 Modified: time.Date(2017, 11, 6, 13, 9, 27, 0, timeZone(-8*time.Hour)), 354 }, 355 }, 356 }, 357 { 358 Name: "utf8-osx.zip", 359 File: []ZipTestFile{ 360 { 361 Name: "世界", 362 Content: []byte{}, 363 Mode: 0644, 364 // Name is valid UTF-8, but format does not have UTF-8 set. 365 NonUTF8: true, 366 Modified: time.Date(2017, 11, 6, 13, 9, 27, 0, timeZone(-8*time.Hour)), 367 }, 368 }, 369 }, 370 { 371 Name: "utf8-winrar.zip", 372 File: []ZipTestFile{ 373 { 374 Name: "世界", 375 Content: []byte{}, 376 Mode: 0666, 377 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867862500, timeZone(-8*time.Hour)), 378 }, 379 }, 380 }, 381 { 382 Name: "utf8-winzip.zip", 383 File: []ZipTestFile{ 384 { 385 Name: "世界", 386 Content: []byte{}, 387 Mode: 0666, 388 Modified: time.Date(2017, 11, 6, 13, 9, 27, 867000000, timeZone(-8*time.Hour)), 389 }, 390 }, 391 }, 392 { 393 Name: "time-7zip.zip", 394 File: []ZipTestFile{ 395 { 396 Name: "test.txt", 397 Content: []byte{}, 398 Size: 1<<32 - 1, 399 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244817900, timeZone(-7*time.Hour)), 400 Mode: 0666, 401 }, 402 }, 403 }, 404 { 405 Name: "time-infozip.zip", 406 File: []ZipTestFile{ 407 { 408 Name: "test.txt", 409 Content: []byte{}, 410 Size: 1<<32 - 1, 411 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)), 412 Mode: 0644, 413 }, 414 }, 415 }, 416 { 417 Name: "time-osx.zip", 418 File: []ZipTestFile{ 419 { 420 Name: "test.txt", 421 Content: []byte{}, 422 Size: 1<<32 - 1, 423 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)), 424 Mode: 0644, 425 }, 426 }, 427 }, 428 { 429 Name: "time-win7.zip", 430 File: []ZipTestFile{ 431 { 432 Name: "test.txt", 433 Content: []byte{}, 434 Size: 1<<32 - 1, 435 Modified: time.Date(2017, 10, 31, 21, 11, 58, 0, time.UTC), 436 Mode: 0666, 437 }, 438 }, 439 }, 440 { 441 Name: "time-winrar.zip", 442 File: []ZipTestFile{ 443 { 444 Name: "test.txt", 445 Content: []byte{}, 446 Size: 1<<32 - 1, 447 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244817900, timeZone(-7*time.Hour)), 448 Mode: 0666, 449 }, 450 }, 451 }, 452 { 453 Name: "time-winzip.zip", 454 File: []ZipTestFile{ 455 { 456 Name: "test.txt", 457 Content: []byte{}, 458 Size: 1<<32 - 1, 459 Modified: time.Date(2017, 10, 31, 21, 11, 57, 244000000, timeZone(-7*time.Hour)), 460 Mode: 0666, 461 }, 462 }, 463 }, 464 { 465 Name: "time-go.zip", 466 File: []ZipTestFile{ 467 { 468 Name: "test.txt", 469 Content: []byte{}, 470 Size: 1<<32 - 1, 471 Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)), 472 Mode: 0666, 473 }, 474 }, 475 }, 476 { 477 Name: "time-22738.zip", 478 File: []ZipTestFile{ 479 { 480 Name: "file", 481 Content: []byte{}, 482 Mode: 0666, 483 Modified: time.Date(1999, 12, 31, 19, 0, 0, 0, timeZone(-5*time.Hour)), 484 ModTime: time.Date(1999, 12, 31, 19, 0, 0, 0, time.UTC), 485 }, 486 }, 487 }, 488 } 489 490 func TestReader(t *testing.T) { 491 for _, zt := range tests { 492 t.Run(zt.Name, func(t *testing.T) { 493 readTestZip(t, zt) 494 }) 495 } 496 } 497 498 func readTestZip(t *testing.T, zt ZipTest) { 499 var z *Reader 500 var err error 501 if zt.Source != nil { 502 rat, size := zt.Source() 503 z, err = NewReader(rat, size) 504 } else { 505 path := filepath.Join("testdata", zt.Name) 506 if zt.Obscured { 507 tf, err := obscuretestdata.DecodeToTempFile(path) 508 if err != nil { 509 t.Errorf("obscuretestdata.DecodeToTempFile(%s): %v", path, err) 510 return 511 } 512 defer os.Remove(tf) 513 path = tf 514 } 515 var rc *ReadCloser 516 rc, err = OpenReader(path) 517 if err == nil { 518 defer rc.Close() 519 z = &rc.Reader 520 } 521 } 522 if err != zt.Error { 523 t.Errorf("error=%v, want %v", err, zt.Error) 524 return 525 } 526 527 // bail if file is not zip 528 if err == ErrFormat { 529 return 530 } 531 532 // bail here if no Files expected to be tested 533 // (there may actually be files in the zip, but we don't care) 534 if zt.File == nil { 535 return 536 } 537 538 if z.Comment != zt.Comment { 539 t.Errorf("comment=%q, want %q", z.Comment, zt.Comment) 540 } 541 if len(z.File) != len(zt.File) { 542 t.Fatalf("file count=%d, want %d", len(z.File), len(zt.File)) 543 } 544 545 // test read of each file 546 for i, ft := range zt.File { 547 readTestFile(t, zt, ft, z.File[i]) 548 } 549 if t.Failed() { 550 return 551 } 552 553 // test simultaneous reads 554 n := 0 555 done := make(chan bool) 556 for i := 0; i < 5; i++ { 557 for j, ft := range zt.File { 558 go func(j int, ft ZipTestFile) { 559 readTestFile(t, zt, ft, z.File[j]) 560 done <- true 561 }(j, ft) 562 n++ 563 } 564 } 565 for ; n > 0; n-- { 566 <-done 567 } 568 } 569 570 func equalTimeAndZone(t1, t2 time.Time) bool { 571 name1, offset1 := t1.Zone() 572 name2, offset2 := t2.Zone() 573 return t1.Equal(t2) && name1 == name2 && offset1 == offset2 574 } 575 576 func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { 577 if f.Name != ft.Name { 578 t.Errorf("name=%q, want %q", f.Name, ft.Name) 579 } 580 if !ft.Modified.IsZero() && !equalTimeAndZone(f.Modified, ft.Modified) { 581 t.Errorf("%s: Modified=%s, want %s", f.Name, f.Modified, ft.Modified) 582 } 583 if !ft.ModTime.IsZero() && !equalTimeAndZone(f.ModTime(), ft.ModTime) { 584 t.Errorf("%s: ModTime=%s, want %s", f.Name, f.ModTime(), ft.ModTime) 585 } 586 587 testFileMode(t, f, ft.Mode) 588 589 size := uint64(f.UncompressedSize) 590 if size == uint32max { 591 size = f.UncompressedSize64 592 } else if size != f.UncompressedSize64 { 593 t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64) 594 } 595 596 r, err := f.Open() 597 if err != nil { 598 t.Errorf("%v", err) 599 return 600 } 601 602 // For very large files, just check that the size is correct. 603 // The content is expected to be all zeros. 604 // Don't bother uncompressing: too big. 605 if ft.Content == nil && ft.File == "" && ft.Size > 0 { 606 if size != ft.Size { 607 t.Errorf("%v: uncompressed size %#x, want %#x", ft.Name, size, ft.Size) 608 } 609 r.Close() 610 return 611 } 612 613 var b bytes.Buffer 614 _, err = io.Copy(&b, r) 615 if err != ft.ContentErr { 616 t.Errorf("copying contents: %v (want %v)", err, ft.ContentErr) 617 } 618 if err != nil { 619 return 620 } 621 r.Close() 622 623 if g := uint64(b.Len()); g != size { 624 t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size) 625 } 626 627 var c []byte 628 if ft.Content != nil { 629 c = ft.Content 630 } else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil { 631 t.Error(err) 632 return 633 } 634 635 if b.Len() != len(c) { 636 t.Errorf("%s: len=%d, want %d", f.Name, b.Len(), len(c)) 637 return 638 } 639 640 for i, b := range b.Bytes() { 641 if b != c[i] { 642 t.Errorf("%s: content[%d]=%q want %q", f.Name, i, b, c[i]) 643 return 644 } 645 } 646 } 647 648 func testFileMode(t *testing.T, f *File, want os.FileMode) { 649 mode := f.Mode() 650 if want == 0 { 651 t.Errorf("%s mode: got %v, want none", f.Name, mode) 652 } else if mode != want { 653 t.Errorf("%s mode: want %v, got %v", f.Name, want, mode) 654 } 655 } 656 657 func TestInvalidFiles(t *testing.T) { 658 const size = 1024 * 70 // 70kb 659 b := make([]byte, size) 660 661 // zeroes 662 _, err := NewReader(bytes.NewReader(b), size) 663 if err != ErrFormat { 664 t.Errorf("zeroes: error=%v, want %v", err, ErrFormat) 665 } 666 667 // repeated directoryEndSignatures 668 sig := make([]byte, 4) 669 binary.LittleEndian.PutUint32(sig, directoryEndSignature) 670 for i := 0; i < size-4; i += 4 { 671 copy(b[i:i+4], sig) 672 } 673 _, err = NewReader(bytes.NewReader(b), size) 674 if err != ErrFormat { 675 t.Errorf("sigs: error=%v, want %v", err, ErrFormat) 676 } 677 678 // negative size 679 _, err = NewReader(bytes.NewReader([]byte("foobar")), -1) 680 if err == nil { 681 t.Errorf("archive/zip.NewReader: expected error when negative size is passed") 682 } 683 } 684 685 func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) { 686 data, err := ioutil.ReadFile(filepath.Join("testdata", fileName)) 687 if err != nil { 688 panic("Error reading " + fileName + ": " + err.Error()) 689 } 690 corrupter(data) 691 return bytes.NewReader(data), int64(len(data)) 692 } 693 694 func returnCorruptCRC32Zip() (r io.ReaderAt, size int64) { 695 return messWith("go-with-datadesc-sig.zip", func(b []byte) { 696 // Corrupt one of the CRC32s in the data descriptor: 697 b[0x2d]++ 698 }) 699 } 700 701 func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) { 702 return messWith("crc32-not-streamed.zip", func(b []byte) { 703 // Corrupt foo.txt's final crc32 byte, in both 704 // the file header and TOC. (0x7e -> 0x7f) 705 b[0x11]++ 706 b[0x9d]++ 707 708 // TODO(bradfitz): add a new test that only corrupts 709 // one of these values, and verify that that's also an 710 // error. Currently, the reader code doesn't verify the 711 // fileheader and TOC's crc32 match if they're both 712 // non-zero and only the second line above, the TOC, 713 // is what matters. 714 }) 715 } 716 717 // rZipBytes returns the bytes of a recursive zip file, without 718 // putting it on disk and triggering certain virus scanners. 719 func rZipBytes() []byte { 720 s := ` 721 0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4 722 0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f 723 0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00 724 0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 725 0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 726 0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00 727 0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8 728 0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f 729 0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e 730 0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb 731 00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff 732 00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 733 00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14 734 00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21 735 00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb 736 00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff 737 0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a 738 0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3 739 0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06 740 0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00 741 0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf 742 0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06 743 0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01 744 0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89 745 0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00 746 0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a 747 00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00 748 00001b0 00 00 6d 01 00 00 00 00` 749 s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "") 750 s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "") 751 b, err := hex.DecodeString(s) 752 if err != nil { 753 panic(err) 754 } 755 return b 756 } 757 758 func returnRecursiveZip() (r io.ReaderAt, size int64) { 759 b := rZipBytes() 760 return bytes.NewReader(b), int64(len(b)) 761 } 762 763 // biggestZipBytes returns the bytes of a zip file biggest.zip 764 // that contains a zip file bigger.zip that contains a zip file 765 // big.zip that contains big.file, which contains 2³²-1 zeros. 766 // The big.zip file is interesting because it has no zip64 header, 767 // much like the innermost zip files in the well-known 42.zip. 768 // 769 // biggest.zip was generated by changing isZip64 to use > uint32max 770 // instead of >= uint32max and then running this program: 771 // 772 // package main 773 // 774 // import ( 775 // "archive/zip" 776 // "bytes" 777 // "io" 778 // "io/ioutil" 779 // "log" 780 // ) 781 // 782 // type zeros struct{} 783 // 784 // func (zeros) Read(b []byte) (int, error) { 785 // for i := range b { 786 // b[i] = 0 787 // } 788 // return len(b), nil 789 // } 790 // 791 // func main() { 792 // bigZip := makeZip("big.file", io.LimitReader(zeros{}, 1<<32-1)) 793 // if err := ioutil.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil { 794 // log.Fatal(err) 795 // } 796 // 797 // biggerZip := makeZip("big.zip", bytes.NewReader(bigZip)) 798 // if err := ioutil.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil { 799 // log.Fatal(err) 800 // } 801 // 802 // biggestZip := makeZip("bigger.zip", bytes.NewReader(biggerZip)) 803 // if err := ioutil.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil { 804 // log.Fatal(err) 805 // } 806 // } 807 // 808 // func makeZip(name string, r io.Reader) []byte { 809 // var buf bytes.Buffer 810 // w := zip.NewWriter(&buf) 811 // wf, err := w.Create(name) 812 // if err != nil { 813 // log.Fatal(err) 814 // } 815 // if _, err = io.Copy(wf, r); err != nil { 816 // log.Fatal(err) 817 // } 818 // if err := w.Close(); err != nil { 819 // log.Fatal(err) 820 // } 821 // return buf.Bytes() 822 // } 823 // 824 // The 4 GB of zeros compresses to 4 MB, which compresses to 20 kB, 825 // which compresses to 1252 bytes (in the hex dump below). 826 // 827 // It's here in hex for the same reason as rZipBytes above: to avoid 828 // problems with on-disk virus scanners or other zip processors. 829 // 830 func biggestZipBytes() []byte { 831 s := ` 832 0000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00 833 0000010 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 62 69 834 0000020 67 67 65 72 2e 7a 69 70 ec dc 6b 4c 53 67 18 07 835 0000030 f0 16 c5 ca 65 2e cb b8 94 20 61 1f 44 33 c7 cd 836 0000040 c0 86 4a b5 c0 62 8a 61 05 c6 cd 91 b2 54 8c 1b 837 0000050 63 8b 03 9c 1b 95 52 5a e3 a0 19 6c b2 05 59 44 838 0000060 64 9d 73 83 71 11 46 61 14 b9 1d 14 09 4a c3 60 839 0000070 2e 4c 6e a5 60 45 02 62 81 95 b6 94 9e 9e 77 e7 840 0000080 d0 43 b6 f8 71 df 96 3c e7 a4 69 ce bf cf e9 79 841 0000090 ce ef 79 3f bf f1 31 db b6 bb 31 76 92 e7 f3 07 842 00000a0 8b fc 9c ca cc 08 cc cb cc 5e d2 1c 88 d9 7e bb 843 00000b0 4f bb 3a 3f 75 f1 5d 7f 8f c2 68 67 77 8f 25 ff 844 00000c0 84 e2 93 2d ef a4 95 3d 71 4e 2c b9 b0 87 c3 be 845 00000d0 3d f8 a7 60 24 61 c5 ef ae 9e c8 6c 6d 4e 69 c8 846 00000e0 67 65 34 f8 37 76 2d 76 5c 54 f3 95 65 49 c7 0f 847 00000f0 18 71 4b 7e 5b 6a d1 79 47 61 41 b0 4e 2a 74 45 848 0000100 43 58 12 b2 5a a5 c6 7d 68 55 88 d4 98 75 18 6d 849 0000110 08 d1 1f 8f 5a 9e 96 ee 45 cf a4 84 4e 4b e8 50 850 0000120 a7 13 d9 06 de 52 81 97 36 b2 d7 b8 fc 2b 5f 55 851 0000130 23 1f 32 59 cf 30 27 fb e2 8a b9 de 45 dd 63 9c 852 0000140 4b b5 8b 96 4c 7a 62 62 cc a1 a7 cf fa f1 fe dd 853 0000150 54 62 11 bf 36 78 b3 c7 b1 b5 f2 61 4d 4e dd 66 854 0000160 32 2e e6 70 34 5f f4 c9 e6 6c 43 6f da 6b c6 c3 855 0000170 09 2c ce 09 57 7f d2 7e b4 23 ba 7c 1b 99 bc 22 856 0000180 3e f1 de 91 2f e3 9c 1b 82 cc c2 84 39 aa e6 de 857 0000190 b4 69 fc cc cb 72 a6 61 45 f0 d3 1d 26 19 7c 8d 858 00001a0 29 c8 66 02 be 77 6a f9 3d 34 79 17 19 c8 96 24 859 00001b0 a3 ac e4 dd 3b 1a 8e c6 fe 96 38 6b bf 67 5a 23 860 00001c0 f4 16 f4 e6 8a b4 fc c2 cd bf 95 66 1d bb 35 aa 861 00001d0 92 7d 66 d8 08 8d a5 1f 54 2a af 09 cf 61 ff d2 862 00001e0 85 9d 8f b6 d7 88 07 4a 86 03 db 64 f3 d9 92 73 863 00001f0 df ec a7 fc 23 4c 8d 83 79 63 2a d9 fd 8d b3 c8 864 0000200 8f 7e d4 19 85 e6 8d 1c 76 f0 8b 58 32 fd 9a d6 865 0000210 85 e2 48 ad c3 d5 60 6f 7e 22 dd ef 09 49 7c 7f 866 0000220 3a 45 c3 71 b7 df f3 4c 63 fb b5 d9 31 5f 6e d6 867 0000230 24 1d a4 4a fe 32 a7 5c 16 48 5c 3e 08 6b 8a d3 868 0000240 25 1d a2 12 a5 59 24 ea 20 5f 52 6d ad 94 db 6b 869 0000250 94 b9 5d eb 4b a7 5c 44 bb 1e f2 3c 6b cf 52 c9 870 0000260 e9 e5 ba 06 b9 c4 e5 0a d0 00 0d d0 00 0d d0 00 871 0000270 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d 872 0000280 d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 873 0000290 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 874 00002a0 0d d0 00 cd ff 9e 46 86 fa a7 7d 3a 43 d7 8e 10 875 00002b0 52 e9 be e6 6e cf eb 9e 85 4d 65 ce cc 30 c1 44 876 00002c0 c0 4e af bc 9c 6c 4b a0 d7 54 ff 1d d5 5c 89 fb 877 00002d0 b5 34 7e c4 c2 9e f5 a0 f6 5b 7e 6e ca 73 c7 ef 878 00002e0 5d be de f9 e8 81 eb a5 0a a5 63 54 2c d7 1c d1 879 00002f0 89 17 85 f8 16 94 f2 8a b2 a3 f5 b6 6d df 75 cd 880 0000300 90 dd 64 bd 5d 55 4e f2 55 19 1b b7 cc ef 1b ea 881 0000310 2e 05 9c f4 aa 1e a8 cd a6 82 c7 59 0f 5e 9d e0 882 0000320 bb fc 6c d6 99 23 eb 36 ad c6 c5 e1 d8 e1 e2 3e 883 0000330 d9 90 5a f7 91 5d 6f bc 33 6d 98 47 d2 7c 2e 2f 884 0000340 99 a4 25 72 85 49 2c be 0b 5b af 8f e5 6e 81 a6 885 0000350 a3 5a 6f 39 53 3a ab 7a 8b 1e 26 f7 46 6c 7d 26 886 0000360 53 b3 22 31 94 d3 83 f2 18 4d f5 92 33 27 53 97 887 0000370 0f d3 e6 55 9c a6 c5 31 87 6f d3 f3 ae 39 6f 56 888 0000380 10 7b ab 7e d0 b4 ca f2 b8 05 be 3f 0e 6e 5a 75 889 0000390 ab 0c f5 37 0e ba 8e 75 71 7a aa ed 7a dd 6a 63 890 00003a0 be 9b a0 97 27 6a 6f e7 d3 8b c4 7c ec d3 91 56 891 00003b0 d9 ac 5e bf 16 42 2f 00 1f 93 a2 23 87 bd e2 59 892 00003c0 a0 de 1a 66 c8 62 eb 55 8f 91 17 b4 61 42 7a 50 893 00003d0 40 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40 894 00003e0 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40 03 895 00003f0 34 40 03 34 40 03 34 ff 85 86 90 8b ea 67 90 0d 896 0000400 e1 42 1b d2 61 d6 79 ec fd 3e 44 28 a4 51 6c 5c 897 0000410 fc d2 72 ca ba 82 18 46 16 61 cd 93 a9 0f d1 24 898 0000420 17 99 e2 2c 71 16 84 0c c8 7a 13 0f 9a 5e c5 f0 899 0000430 79 64 e2 12 4d c8 82 a1 81 19 2d aa 44 6d 87 54 900 0000440 84 71 c1 f6 d4 ca 25 8c 77 b9 08 c7 c8 5e 10 8a 901 0000450 8f 61 ed 8c ba 30 1f 79 9a c7 60 34 2b b9 8c f8 902 0000460 18 a6 83 1b e3 9f ad 79 fe fd 1b 8b f1 fc 41 6f 903 0000470 d4 13 1f e3 b8 83 ba 64 92 e7 eb e4 77 05 8f ba 904 0000480 fa 3b 00 00 ff ff 50 4b 07 08 a6 18 b1 91 5e 04 905 0000490 00 00 e4 47 00 00 50 4b 01 02 14 00 14 00 08 00 906 00004a0 08 00 00 00 00 00 a6 18 b1 91 5e 04 00 00 e4 47 907 00004b0 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 908 00004c0 00 00 00 00 62 69 67 67 65 72 2e 7a 69 70 50 4b 909 00004d0 05 06 00 00 00 00 01 00 01 00 38 00 00 00 96 04 910 00004e0 00 00 00 00` 911 s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "") 912 s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "") 913 b, err := hex.DecodeString(s) 914 if err != nil { 915 panic(err) 916 } 917 return b 918 } 919 920 func returnBigZipBytes() (r io.ReaderAt, size int64) { 921 b := biggestZipBytes() 922 for i := 0; i < 2; i++ { 923 r, err := NewReader(bytes.NewReader(b), int64(len(b))) 924 if err != nil { 925 panic(err) 926 } 927 f, err := r.File[0].Open() 928 if err != nil { 929 panic(err) 930 } 931 b, err = ioutil.ReadAll(f) 932 if err != nil { 933 panic(err) 934 } 935 } 936 return bytes.NewReader(b), int64(len(b)) 937 } 938 939 func TestIssue8186(t *testing.T) { 940 // Directory headers & data found in the TOC of a JAR file. 941 dirEnts := []string{ 942 "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", 943 "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", 944 "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", 945 "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", 946 "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", 947 "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", 948 "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", 949 "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", 950 "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", 951 } 952 for i, s := range dirEnts { 953 var f File 954 err := readDirectoryHeader(&f, strings.NewReader(s)) 955 if err != nil { 956 t.Errorf("error reading #%d: %v", i, err) 957 } 958 } 959 } 960 961 // Verify we return ErrUnexpectedEOF when length is short. 962 func TestIssue10957(t *testing.T) { 963 data := []byte("PK\x03\x040000000PK\x01\x0200000" + 964 "0000000000000000000\x00" + 965 "\x00\x00\x00\x00\x00000000000000PK\x01" + 966 "\x020000000000000000000" + 967 "00000\v\x00\x00\x00\x00\x00000000000" + 968 "00000000000000PK\x01\x0200" + 969 "00000000000000000000" + 970 "00\v\x00\x00\x00\x00\x00000000000000" + 971 "00000000000PK\x01\x020000<" + 972 "0\x00\x0000000000000000\v\x00\v" + 973 "\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" + 974 "00000000PK\x01\x0200000000" + 975 "0000000000000000\v\x00\x00\x00" + 976 "\x00\x0000PK\x05\x06000000\x05\x000000" + 977 "\v\x00\x00\x00\x00\x00") 978 z, err := NewReader(bytes.NewReader(data), int64(len(data))) 979 if err != nil { 980 t.Fatal(err) 981 } 982 for i, f := range z.File { 983 r, err := f.Open() 984 if err != nil { 985 continue 986 } 987 if f.UncompressedSize64 < 1e6 { 988 n, err := io.Copy(ioutil.Discard, r) 989 if i == 3 && err != io.ErrUnexpectedEOF { 990 t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err) 991 } 992 if err == nil && uint64(n) != f.UncompressedSize64 { 993 t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64) 994 } 995 } 996 r.Close() 997 } 998 } 999 1000 // Verify that this particular malformed zip file is rejected. 1001 func TestIssue10956(t *testing.T) { 1002 data := []byte("PK\x06\x06PK\x06\a0000\x00\x00\x00\x00\x00\x00\x00\x00" + 1003 "0000PK\x05\x06000000000000" + 1004 "0000\v\x00000\x00\x00\x00\x00\x00\x00\x000") 1005 r, err := NewReader(bytes.NewReader(data), int64(len(data))) 1006 if err == nil { 1007 t.Errorf("got nil error, want ErrFormat") 1008 } 1009 if r != nil { 1010 t.Errorf("got non-nil Reader, want nil") 1011 } 1012 } 1013 1014 // Verify we return ErrUnexpectedEOF when reading truncated data descriptor. 1015 func TestIssue11146(t *testing.T) { 1016 data := []byte("PK\x03\x040000000000000000" + 1017 "000000\x01\x00\x00\x000\x01\x00\x00\xff\xff0000" + 1018 "0000000000000000PK\x01\x02" + 1019 "0000\b0\b\x00000000000000" + 1020 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000PK\x05\x06\x00\x00" + 1021 "\x00\x0000\x01\x0000008\x00\x00\x00\x00\x00") 1022 z, err := NewReader(bytes.NewReader(data), int64(len(data))) 1023 if err != nil { 1024 t.Fatal(err) 1025 } 1026 r, err := z.File[0].Open() 1027 if err != nil { 1028 t.Fatal(err) 1029 } 1030 _, err = ioutil.ReadAll(r) 1031 if err != io.ErrUnexpectedEOF { 1032 t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err) 1033 } 1034 r.Close() 1035 } 1036 1037 // Verify we do not treat non-zip64 archives as zip64 1038 func TestIssue12449(t *testing.T) { 1039 data := []byte{ 1040 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00, 1041 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46, 0x00, 0x00, 1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1043 0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0xca, 0x64, 1044 0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05, 1045 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 1046 0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 1047 0x00, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x0a, 1048 0x50, 0x4b, 0x07, 0x08, 0x1d, 0x88, 0x77, 0xb0, 1049 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 1050 0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00, 1051 0x08, 0x00, 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46, 1052 0x1d, 0x88, 0x77, 0xb0, 0x07, 0x00, 0x00, 0x00, 1053 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 1054 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1055 0xa0, 0x81, 0x00, 0x00, 0x00, 0x00, 0xca, 0x64, 1056 0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05, 1057 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 1058 0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 1059 0x00, 0x97, 0x2b, 0x49, 0x23, 0x05, 0xc5, 0x0b, 1060 0xa7, 0xd1, 0x52, 0xa2, 0x9c, 0x50, 0x4b, 0x06, 1061 0x07, 0xc8, 0x19, 0xc1, 0xaf, 0x94, 0x9c, 0x61, 1062 0x44, 0xbe, 0x94, 0x19, 0x42, 0x58, 0x12, 0xc6, 1063 0x5b, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 1064 0x00, 0x01, 0x00, 0x01, 0x00, 0x69, 0x00, 0x00, 1065 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 1066 } 1067 // Read in the archive. 1068 _, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data))) 1069 if err != nil { 1070 t.Errorf("Error reading the archive: %v", err) 1071 } 1072 }