From 10e8e937100833d222e46fed5cae38bd70cb5298 Mon Sep 17 00:00:00 2001 From: Nan Zhang Date: Tue, 19 Sep 2017 17:13:11 -0700 Subject: [PATCH] Strip extended-timestap extra block in zip2zip. The extended-timestap extra block changes between Local File Header and Central Directory. We have to strip it out to avoid mis-filling during zip2zip. Bug: b/65455145 Test: add unit-test. Change-Id: I17e3f6c10fd6a068019620b4426f6042f6fac317 --- third_party/zip/android.go | 25 +++++++++++++++---------- third_party/zip/android_test.go | 7 ++++++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/third_party/zip/android.go b/third_party/zip/android.go index d35513fd7..8d387ccb1 100644 --- a/third_party/zip/android.go +++ b/third_party/zip/android.go @@ -20,6 +20,7 @@ import ( ) const DataDescriptorFlag = 0x8 +const ExtendedTimeStampTag = 0x5455 func (w *Writer) CopyFrom(orig *File, newName string) error { if w.last != nil && !w.last.closed { @@ -33,11 +34,9 @@ func (w *Writer) CopyFrom(orig *File, newName string) error { fileHeader.Name = newName fh := &fileHeader - // The zip64 extras change between the Central Directory and Local File Header, while we use - // the same structure for both. The Local File Haeder is taken care of by us writing a data - // descriptor with the zip64 values. The Central Directory Entry is written by Close(), where - // the zip64 extra is automatically created and appended when necessary. - fh.Extra = stripZip64Extras(fh.Extra) + // In some cases, we need strip the extras if it change between Central Directory + // and Local File Header. + fh.Extra = stripExtras(fh.Extra) h := &header{ FileHeader: fh, @@ -48,8 +47,6 @@ func (w *Writer) CopyFrom(orig *File, newName string) error { if err := writeHeader(w.cw, fh); err != nil { return err } - - // Copy data dataOffset, err := orig.DataOffset() if err != nil { return err @@ -79,8 +76,16 @@ func (w *Writer) CopyFrom(orig *File, newName string) error { return err } -// Strip any Zip64 extra fields -func stripZip64Extras(input []byte) []byte { +// The zip64 extras change between the Central Directory and Local File Header, while we use +// the same structure for both. The Local File Haeder is taken care of by us writing a data +// descriptor with the zip64 values. The Central Directory Entry is written by Close(), where +// the zip64 extra is automatically created and appended when necessary. +// +// The extended-timestamp extra block changes between the Central Directory Header and Local +// File Header. +// Extended-Timestamp extra(LFH): +// Extended-Timestamp extra(CDH): +func stripExtras(input []byte) []byte { ret := []byte{} for len(input) >= 4 { @@ -90,7 +95,7 @@ func stripZip64Extras(input []byte) []byte { if int(size) > len(r) { break } - if tag != zip64ExtraId { + if tag != zip64ExtraId && tag != ExtendedTimeStampTag { ret = append(ret, input[:4+size]...) } input = input[4+size:] diff --git a/third_party/zip/android_test.go b/third_party/zip/android_test.go index cdf66ff60..5154a17b3 100644 --- a/third_party/zip/android_test.go +++ b/third_party/zip/android_test.go @@ -59,11 +59,16 @@ var stripZip64Testcases = []struct { in: []byte{0, 0, 8, 0, 0, 0}, out: []byte{0, 0, 8, 0, 0, 0}, }, + { + name: "zip64 extra and extended-timestamp extra and valid non-zip64 extra", + in: []byte{1, 0, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 85, 84, 5, 0, 1, 1, 2, 3, 4, 2, 0, 0, 0}, + out: []byte{2, 0, 0, 0}, + }, } func TestStripZip64Extras(t *testing.T) { for _, testcase := range stripZip64Testcases { - got := stripZip64Extras(testcase.in) + got := stripExtras(testcase.in) if !bytes.Equal(got, testcase.out) { t.Errorf("Failed testcase %s\ninput: %v\n want: %v\n got: %v\n", testcase.name, testcase.in, testcase.out, got) }