Store real number of records in regular end record when possible
Only store uintmax for the number of entries in the regular end record if it doesn't fit. p7zip 16.02 rejects zip files where the number of entries in the regular end record is larger than the number of entries counted in the central directory. Fixes: 187485108 Test: TestZip64P7ZipRecords Change-Id: I0d116e228a0ee26e4e95bb3f35771da236a056eb
This commit is contained in:
parent
ee7e359131
commit
06eea2c9b8
|
@ -140,3 +140,83 @@ func TestCopyFromZip64(t *testing.T) {
|
||||||
t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
|
t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for b/187485108: zip64 output can't be read by p7zip 16.02.
|
||||||
|
func TestZip64P7ZipRecords(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("slow test; skipping")
|
||||||
|
}
|
||||||
|
|
||||||
|
const size = uint32max + 1
|
||||||
|
zipBytes := &bytes.Buffer{}
|
||||||
|
zip := NewWriter(zipBytes)
|
||||||
|
f, err := zip.CreateHeaderAndroid(&FileHeader{
|
||||||
|
Name: "large",
|
||||||
|
Method: Store,
|
||||||
|
UncompressedSize64: size,
|
||||||
|
CompressedSize64: size,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Create: %v", err)
|
||||||
|
}
|
||||||
|
_, err = f.Write(make([]byte, size))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Write: %v", err)
|
||||||
|
}
|
||||||
|
err = zip.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Close: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := zipBytes.Bytes()
|
||||||
|
p := findSignatureInBlock(buf)
|
||||||
|
if p < 0 {
|
||||||
|
t.Fatalf("Missing signature")
|
||||||
|
}
|
||||||
|
|
||||||
|
b := readBuf(buf[p+4:]) // skip signature
|
||||||
|
d := &directoryEnd{
|
||||||
|
diskNbr: uint32(b.uint16()),
|
||||||
|
dirDiskNbr: uint32(b.uint16()),
|
||||||
|
dirRecordsThisDisk: uint64(b.uint16()),
|
||||||
|
directoryRecords: uint64(b.uint16()),
|
||||||
|
directorySize: uint64(b.uint32()),
|
||||||
|
directoryOffset: uint64(b.uint32()),
|
||||||
|
commentLen: b.uint16(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// p7zip 16.02 wants regular end record directoryRecords to be accurate.
|
||||||
|
if g, w := d.directoryRecords, uint64(1); g != w {
|
||||||
|
t.Errorf("wanted directoryRecords %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := d.directorySize, uint64(uint32max); g != w {
|
||||||
|
t.Errorf("wanted directorySize %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := d.directoryOffset, uint64(uint32max); g != w {
|
||||||
|
t.Errorf("wanted directoryOffset %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(buf)
|
||||||
|
|
||||||
|
p64, err := findDirectory64End(r, int64(p))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("findDirectory64End: %v", err)
|
||||||
|
}
|
||||||
|
if p < 0 {
|
||||||
|
t.Fatalf("findDirectory64End: not found")
|
||||||
|
}
|
||||||
|
err = readDirectory64End(r, p64, d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("readDirectory64End: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := d.directoryRecords, uint64(1); g != w {
|
||||||
|
t.Errorf("wanted directoryRecords %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, w := d.directoryOffset, uint64(uint32max); g <= w {
|
||||||
|
t.Errorf("wanted directoryOffset > %d, got %d", w, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -155,7 +155,14 @@ func (w *Writer) Close() error {
|
||||||
|
|
||||||
// store max values in the regular end record to signal that
|
// store max values in the regular end record to signal that
|
||||||
// that the zip64 values should be used instead
|
// that the zip64 values should be used instead
|
||||||
|
// BEGIN ANDROID CHANGE: only store uintmax for the number of entries in the regular
|
||||||
|
// end record if it doesn't fit. p7zip 16.02 rejects zip files where the number of
|
||||||
|
// entries in the regular end record is larger than the number of entries counted
|
||||||
|
// in the central directory.
|
||||||
|
if records > uint16max {
|
||||||
records = uint16max
|
records = uint16max
|
||||||
|
}
|
||||||
|
// END ANDROID CHANGE
|
||||||
size = uint32max
|
size = uint32max
|
||||||
offset = uint32max
|
offset = uint32max
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue