diff --git a/storage/storage.go b/storage/storage.go index 49e8cb3dbbe9..c01085f35dda 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -1096,6 +1096,10 @@ func (o *ObjectHandle) validate() error { if !utf8.ValidString(o.object) { return fmt.Errorf("storage: object name %q is not valid UTF-8", o.object) } + // Names . and .. are not valid; see https://cloud.google.com/storage/docs/objects#naming + if o.object == "." || o.object == ".." { + return fmt.Errorf("storage: object name %q is not valid", o.object) + } return nil } diff --git a/storage/storage_test.go b/storage/storage_test.go index 448e92c8f7f8..5d37ea50821f 100644 --- a/storage/storage_test.go +++ b/storage/storage_test.go @@ -2424,6 +2424,57 @@ func TestParseProjectNumber(t *testing.T) { } } +func TestObjectValidate(t *testing.T) { + for _, c := range []struct { + name string + bucket string + object string + wantSuccess bool + }{ + { + name: "valid object", + bucket: "my-bucket", + object: "my-object", + wantSuccess: true, + }, + { + name: "empty bucket name", + bucket: "", + object: "my-object", + wantSuccess: false, + }, + { + name: "empty object name", + bucket: "my-bucket", + object: "", + wantSuccess: false, + }, + { + name: "invalid utf-8", + bucket: "my-bucket", + object: "\xc3\x28", + wantSuccess: false, + }, + { + name: "object name .", + bucket: "my-bucket", + object: ".", + wantSuccess: false, + }, + } { + t.Run(c.name, func(r *testing.T) { + b := &BucketHandle{name: c.bucket} + err := b.Object(c.object).validate() + if c.wantSuccess && err != nil { + r.Errorf("want success, got error %v", err) + } + if !c.wantSuccess && err == nil { + r.Errorf("want error, got nil") + } + }) + } +} + // isZeroValue reports whether v is the zero value for its type // It errors if the argument is unknown func isZeroValue(v reflect.Value) (bool, error) {