From 4e998d71c9abf1a2d302307301688108ccfffc56 Mon Sep 17 00:00:00 2001 From: Marco Hennings Date: Fri, 6 Sep 2013 16:49:38 -0400 Subject: [PATCH] archive/tar: fix a case where USTAR-split is not working correctly. 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 | 7 ++++-- src/pkg/archive/tar/writer_test.go | 36 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/pkg/archive/tar/writer.go b/src/pkg/archive/tar/writer.go index c0325194a2..549f1464c3 100644 --- a/src/pkg/archive/tar/writer.go +++ b/src/pkg/archive/tar/writer.go @@ -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 } diff --git a/src/pkg/archive/tar/writer_test.go b/src/pkg/archive/tar/writer_test.go index cddcbbc254..30ebf977ac 100644 --- a/src/pkg/archive/tar/writer_test.go +++ b/src/pkg/archive/tar/writer_test.go @@ -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") + } +} -- 2.48.1