diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go index e426c72ffe9cc3..dadb455735216f 100644 --- a/src/archive/tar/reader.go +++ b/src/archive/tar/reader.go @@ -46,9 +46,9 @@ func NewReader(r io.Reader) *Reader { // At the end of the archive, Next returns the error io.EOF. // // If Next encounters a non-local file name (as defined by [filepath.IsLocal]) -// and the GODEBUG environment variable contains `tarinsecurepath=0`, +// and the GODEBUG environment variable contains `tarinsecurepath=0`, Next +// returns the header with an [ErrInsecurePath] error. // Only file names are validated, not link targets. -// Next returns the header with an [ErrInsecurePath] error. // A future version of Go may introduce this behavior by default. // Programs that want to accept non-local names can ignore // the [ErrInsecurePath] error and use the returned header. diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index a324674cb7bb19..45b69387af9827 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -1684,6 +1684,51 @@ func TestInsecurePaths(t *testing.T) { } } +func TestInsecureLinknames(t *testing.T) { + t.Setenv("GODEBUG", "tarinsecurepath=0") + for _, test := range []struct { + name string + typeflag byte + linkname string + }{ + { + name: "hardlink", + typeflag: TypeLink, + linkname: "../target", + }, + { + name: "symlink", + typeflag: TypeSymlink, + linkname: "/target", + }, + } { + var buf bytes.Buffer + tw := NewWriter(&buf) + if err := tw.WriteHeader(&Header{ + Name: test.name, + Typeflag: test.typeflag, + Linkname: test.linkname, + }); err != nil { + t.Fatalf("WriteHeader(%s): %v", test.name, err) + } + if err := tw.Close(); err != nil { + t.Fatalf("Close(%s): %v", test.name, err) + } + + tr := NewReader(&buf) + h, err := tr.Next() + if err != nil { + t.Fatalf("Next(%s): got err %v, want nil", test.name, err) + } + if h.Name != test.name { + t.Errorf("Next(%s): got name %q, want %q", test.name, h.Name, test.name) + } + if h.Linkname != test.linkname { + t.Errorf("Next(%s): got linkname %q, want %q", test.name, h.Linkname, test.linkname) + } + } +} + func TestDisableInsecurePathCheck(t *testing.T) { t.Setenv("GODEBUG", "tarinsecurepath=1") var buf bytes.Buffer