ソースを参照

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
Nan Zhang 6 年 前
コミット
10e8e93710
2 ファイル変更21 行追加11 行削除
  1. 15 10
      third_party/zip/android.go
  2. 6 1
      third_party/zip/android_test.go

+ 15 - 10
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): <tag-size-flag-modtime-actime-changetime>
+// Extended-Timestamp extra(CDH): <tag-size-flag-modtime>
+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:]

+ 6 - 1
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)
 		}