mirror of
https://github.com/golang/go
synced 2024-11-23 20:40:07 -07:00
archive/tar: improve handling of directory paths
The USTAR format says: <<< Implementors should be aware that the previous file format did not include a mechanism to archive directory type files. For this reason, the convention of using a filename ending with <slash> was adopted to specify a directory on the archive. >>> In light of this suggestion, make the following changes: * Writer.WriteHeader refuses to encode a header where a file that is obviously a file-type has a trailing slash in the name. * formatter.formatString avoids encoding a trailing slash in the event that the string is truncated (the full string will be encoded elsewhere, so stripping the slash is safe). * Reader.Next treats a TypeRegA (which is the zero value of Typeflag) as a TypeDir if the name has a trailing slash. Change-Id: Ibf27aa8234cce2032d92e5e5b28546c2f2ae5ef6 Reviewed-on: https://go-review.googlesource.com/69293 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
d63de28711
commit
4cd58c2f26
@ -444,6 +444,11 @@ func (h *Header) allowedFormats() (format Format, paxHdrs map[string]string, err
|
||||
// Check for header-only types.
|
||||
var whyOnlyPAX, whyOnlyGNU string
|
||||
switch h.Typeflag {
|
||||
case TypeReg, TypeChar, TypeBlock, TypeFifo, TypeGNUSparse:
|
||||
// Exclude TypeLink and TypeSymlink, since they may reference directories.
|
||||
if strings.HasSuffix(h.Name, "/") {
|
||||
return FormatUnknown, nil, headerError{"filename may not have trailing slash"}
|
||||
}
|
||||
case TypeXHeader, TypeGNULongName, TypeGNULongLink:
|
||||
return FormatUnknown, nil, headerError{"cannot manually encode TypeXHeader, TypeGNULongName, or TypeGNULongLink headers"}
|
||||
case TypeXGlobalHeader:
|
||||
|
@ -130,6 +130,9 @@ loop:
|
||||
if gnuLongLink != "" {
|
||||
hdr.Linkname = gnuLongLink
|
||||
}
|
||||
if hdr.Typeflag == TypeRegA && strings.HasSuffix(hdr.Name, "/") {
|
||||
hdr.Typeflag = TypeDir // Legacy archives use trailing slash for directories
|
||||
}
|
||||
|
||||
// The extended headers may have updated the size.
|
||||
// Thus, setup the regFileReader again after merging PAX headers.
|
||||
|
@ -675,6 +675,17 @@ func TestReader(t *testing.T) {
|
||||
},
|
||||
Format: FormatPAX,
|
||||
}},
|
||||
}, {
|
||||
file: "testdata/trailing-slash.tar",
|
||||
headers: []*Header{{
|
||||
Typeflag: TypeDir,
|
||||
Name: strings.Repeat("123456789/", 30),
|
||||
ModTime: time.Unix(0, 0),
|
||||
PAXRecords: map[string]string{
|
||||
"path": strings.Repeat("123456789/", 30),
|
||||
},
|
||||
Format: FormatPAX,
|
||||
}},
|
||||
}}
|
||||
|
||||
for _, v := range vectors {
|
||||
|
@ -68,6 +68,14 @@ func (f *formatter) formatString(b []byte, s string) {
|
||||
if len(s) < len(b) {
|
||||
b[len(s)] = 0
|
||||
}
|
||||
|
||||
// Some buggy readers treat regular files with a trailing slash
|
||||
// in the V7 path field as a directory even though the full path
|
||||
// recorded elsewhere (e.g., via PAX record) contains no trailing slash.
|
||||
if len(s) > len(b) && b[len(b)-1] == '/' {
|
||||
n := len(strings.TrimRight(s[:len(b)], "/"))
|
||||
b[n] = 0 // Replace trailing slash with NUL terminator
|
||||
}
|
||||
}
|
||||
|
||||
// fitsInBase256 reports whether x can be encoded into n bytes using base-256
|
||||
|
@ -748,6 +748,15 @@ func TestHeaderAllowedFormats(t *testing.T) {
|
||||
}, {
|
||||
header: &Header{Name: "sparse.db", Size: 1000, SparseHoles: []SparseEntry{{0, 500}}, Format: FormatUSTAR},
|
||||
formats: FormatUnknown,
|
||||
}, {
|
||||
header: &Header{Name: "foo/", Typeflag: TypeDir},
|
||||
formats: FormatUSTAR | FormatPAX | FormatGNU,
|
||||
}, {
|
||||
header: &Header{Name: "foo/", Typeflag: TypeReg},
|
||||
formats: FormatUnknown,
|
||||
}, {
|
||||
header: &Header{Name: "foo/", Typeflag: TypeSymlink},
|
||||
formats: FormatUSTAR | FormatPAX | FormatGNU,
|
||||
}}
|
||||
|
||||
for i, v := range vectors {
|
||||
|
BIN
src/archive/tar/testdata/trailing-slash.tar
vendored
Normal file
BIN
src/archive/tar/testdata/trailing-slash.tar
vendored
Normal file
Binary file not shown.
@ -323,6 +323,7 @@ func (tw *Writer) writeRawFile(name, data string, flag byte, format Format) erro
|
||||
if len(name) > nameSize {
|
||||
name = name[:nameSize]
|
||||
}
|
||||
name = strings.TrimRight(name, "/")
|
||||
|
||||
var f formatter
|
||||
v7 := tw.blk.V7()
|
||||
|
@ -451,6 +451,12 @@ func TestWriter(t *testing.T) {
|
||||
}, 6e10, nil},
|
||||
testClose{nil},
|
||||
},
|
||||
}, {
|
||||
file: "testdata/trailing-slash.tar",
|
||||
tests: []testFnc{
|
||||
testHeader{Header{Name: strings.Repeat("123456789/", 30)}, nil},
|
||||
testClose{nil},
|
||||
},
|
||||
}}
|
||||
|
||||
equalError := func(x, y error) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user