]> Cypherpunks repositories - gostls13.git/commitdiff
archive/tar: fix a case where USTAR-split is not working correctly.
authorMarco Hennings <marco.hennings@freiheit.com>
Fri, 6 Sep 2013 20:49:38 +0000 (16:49 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 6 Sep 2013 20:49:38 +0000 (16:49 -0400)
For some long filenames the USTAR-split code does not work
correctly. It is wrongly assumed that the path would not be too long,
but it is.

The user visible result was that a filename was split, but it still
caused an error.

The cause was a wrongly calculated nlen. In addition I noticed that
at this place it is also seems necessary to check if the prefix will
fit in the 155 chars available for the prefix.

R=dsymonds, rsc
CC=golang-dev
https://golang.org/cl/13300046

src/pkg/archive/tar/writer.go
src/pkg/archive/tar/writer_test.go

index c0325194a2c4267e2b7f2ad0c7836762f0bbcbb2..549f1464c38b0b2667843f1ba3db9c967525d3f7 100644 (file)
@@ -263,8 +263,11 @@ func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err er
                length--
        }
        i := strings.LastIndex(name[:length], "/")
-       nlen := length - i - 1
-       if i <= 0 || nlen > fileNameSize || nlen == 0 {
+       // nlen contains the resulting length in the name field.
+       // plen contains the resulting length in the prefix field.
+       nlen := len(name) - i - 1
+       plen := i
+       if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
                err = errNameTooLong
                return
        }
index cddcbbc254f7e67938ae3d09fd00f766acbfbd68..30ebf977acfc09f9c0764065004526069f12cd2b 100644 (file)
@@ -355,3 +355,39 @@ func TestPAXHeader(t *testing.T) {
                }
        }
 }
+
+func TestUSTARLongName(t *testing.T) {
+       // Create an archive with a path that failed to split with USTAR extension in previous versions.
+       fileinfo, err := os.Stat("testdata/small.txt")
+       if err != nil {
+               t.Fatal(err)
+       }
+       hdr, err := FileInfoHeader(fileinfo, "")
+       hdr.Typeflag = TypeDir
+       if err != nil {
+               t.Fatalf("os.Stat:1 %v", err)
+       }
+       // Force a PAX long name to be written. The name was taken from a practical example
+       // that fails and replaced ever char through numbers to anonymize the sample.
+       longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/"
+       hdr.Name = longName
+
+       hdr.Size = 0
+       var buf bytes.Buffer
+       writer := NewWriter(&buf)
+       if err := writer.WriteHeader(hdr); err != nil {
+               t.Fatal(err)
+       }
+       if err := writer.Close(); err != nil {
+               t.Fatal(err)
+       }
+       // Test that we can get a long name back out of the archive.
+       reader := NewReader(&buf)
+       hdr, err = reader.Next()
+       if err != nil {
+               t.Fatal(err)
+       }
+       if hdr.Name != longName {
+               t.Fatal("Couldn't recover long name")
+       }
+}