diff --git a/txtar.go b/txtar.go index 591dcbf..7c9a105 100644 --- a/txtar.go +++ b/txtar.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "path" + "path/filepath" "strings" "golang.org/x/tools/txtar" @@ -89,6 +90,7 @@ func splitFiles(src []byte) (*fileSet, error) { if numFiles > limitNumFiles { return nil, fmt.Errorf("too many files in txtar archive (%v exceeds limit of %v)", numFiles, limitNumFiles) } + dirFileNameMap := map[string]string{} // holds which filename the dirname is part of for _, f := range a.Files { if len(f.Name) > 200 { // arbitrary limit return nil, errors.New("file name too long") @@ -111,6 +113,16 @@ func splitFiles(src []byte) (*fileSet, error) { if fs.Contains(f.Name) { return nil, fmt.Errorf("duplicate file name %q", f.Name) } + for i := 1; i < len(parts); i++ { + dirname := filepath.Join(parts[:i]...) + if fs.Contains(dirname) { + return nil, fmt.Errorf("conflict file/dir name %q and %q", dirname, f.Name) + } + dirFileNameMap[dirname] = f.Name + } + if filename, ok := dirFileNameMap[f.Name]; ok { + return nil, fmt.Errorf("conflict dir/file name %q and %q", filename, f.Name) + } fs.AddFile(f.Name, f.Data) } return fs, nil diff --git a/txtar_test.go b/txtar_test.go index 493d140..5297c1c 100644 --- a/txtar_test.go +++ b/txtar_test.go @@ -117,6 +117,16 @@ func TestSplitFiles(t *testing.T) { in: strings.Repeat("-- x.go --\n", 50), wantErr: `too many files in txtar archive (50 exceeds limit of 20)`, }, + { + name: "reject file overwritten by dir", + in: "-- a --\n-- a/b --\n", + wantErr: `conflict file/dir name "a" and "a/b"`, + }, + { + name: "reject dir overwritten by file", + in: "-- a/b --\n-- a --\n", + wantErr: `conflict dir/file name "a/b" and "a"`, + }, } { got, err := splitFiles([]byte(tt.in)) var gotErr string