fs/erasure: Ignore objects with / even for DeleteObject() (#4303)

Additionally GetObject() also returns errFileNotFound similar
to HeadObject().

Fixes #4302
master
Harshavardhana 8 years ago committed by GitHub
parent fc774957fe
commit 298b470f69
  1. 9
      cmd/fs-v1.go
  2. 4
      cmd/object-api-input-checks.go
  3. 5
      cmd/object-api-utils.go
  4. 33
      cmd/server_test.go
  5. 8
      cmd/xl-v1-object.go
  6. 4
      cmd/xl-v1-object_test.go

@ -473,6 +473,7 @@ func (fs fsObjects) CopyObject(srcBucket, srcObject, dstBucket, dstObject string
// startOffset indicates the starting read location of the object. // startOffset indicates the starting read location of the object.
// length indicates the total length of the object. // length indicates the total length of the object.
func (fs fsObjects) GetObject(bucket, object string, offset int64, length int64, writer io.Writer) (err error) { func (fs fsObjects) GetObject(bucket, object string, offset int64, length int64, writer io.Writer) (err error) {
// This is a special case with object whose name ends with
if err = checkGetObjArgs(bucket, object); err != nil { if err = checkGetObjArgs(bucket, object); err != nil {
return err return err
} }
@ -568,12 +569,6 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) {
// GetObjectInfo - reads object metadata and replies back ObjectInfo. // GetObjectInfo - reads object metadata and replies back ObjectInfo.
func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
// This is a special case with object whose name ends with
// a slash separator, we always return object not found here.
if hasSuffix(object, slashSeparator) {
return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object)
}
if err := checkGetObjArgs(bucket, object); err != nil { if err := checkGetObjArgs(bucket, object); err != nil {
return ObjectInfo{}, err return ObjectInfo{}, err
} }
@ -591,13 +586,13 @@ func (fs fsObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
// for future object operations. // for future object operations.
func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.Reader, metadata map[string]string, sha256sum string) (objInfo ObjectInfo, retErr error) { func (fs fsObjects) PutObject(bucket string, object string, size int64, data io.Reader, metadata map[string]string, sha256sum string) (objInfo ObjectInfo, retErr error) {
var err error var err error
// This is a special case with size as '0' and object ends with // This is a special case with size as '0' and object ends with
// a slash separator, we treat it like a valid operation and // a slash separator, we treat it like a valid operation and
// return success. // return success.
if isObjectDir(object, size) { if isObjectDir(object, size) {
return dirObjectInfo(bucket, object, size, metadata), nil return dirObjectInfo(bucket, object, size, metadata), nil
} }
if err = checkPutObjectArgs(bucket, object, fs); err != nil { if err = checkPutObjectArgs(bucket, object, fs); err != nil {
return ObjectInfo{}, err return ObjectInfo{}, err
} }

@ -36,6 +36,10 @@ func checkBucketAndObjectNames(bucket, object string) error {
} }
// Verify if object is valid. // Verify if object is valid.
if !IsValidObjectName(object) { if !IsValidObjectName(object) {
// Objects with "/" are invalid, verify to return a different error.
if hasSuffix(object, slashSeparator) || hasPrefix(object, slashSeparator) {
return traceError(ObjectNotFound{Bucket: bucket, Object: object})
}
return traceError(ObjectNameInvalid{Bucket: bucket, Object: object}) return traceError(ObjectNameInvalid{Bucket: bucket, Object: object})
} }
return nil return nil

@ -119,10 +119,7 @@ func IsValidObjectName(object string) bool {
if len(object) == 0 { if len(object) == 0 {
return false return false
} }
if hasSuffix(object, slashSeparator) { if hasSuffix(object, slashSeparator) || hasPrefix(object, slashSeparator) {
return false
}
if hasPrefix(object, slashSeparator) {
return false return false
} }
return IsValidObjectPrefix(object) return IsValidObjectPrefix(object)

@ -171,6 +171,39 @@ func (s *TestSuiteCommon) TestObjectDir(c *C) {
c.Assert(err, IsNil) c.Assert(err, IsNil)
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest) verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest)
request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, "my-object-directory/"),
0, nil, s.accessKey, s.secretKey, s.signer)
c.Assert(err, IsNil)
client = http.Client{Transport: s.transport}
// execute the HTTP request.
response, err = client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusNotFound)
request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, "my-object-directory/"),
0, nil, s.accessKey, s.secretKey, s.signer)
c.Assert(err, IsNil)
client = http.Client{Transport: s.transport}
// execute the HTTP request.
response, err = client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusNotFound)
request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, "my-object-directory/"),
0, nil, s.accessKey, s.secretKey, s.signer)
c.Assert(err, IsNil)
client = http.Client{Transport: s.transport}
// execute the HTTP request.
response, err = client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusNoContent)
} }
func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *C) { func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *C) {

@ -320,12 +320,6 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i
// GetObjectInfo - reads object metadata and replies back ObjectInfo. // GetObjectInfo - reads object metadata and replies back ObjectInfo.
func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) { func (xl xlObjects) GetObjectInfo(bucket, object string) (ObjectInfo, error) {
// This is a special case with object whose name ends with
// a slash separator, we always return object not found here.
if hasSuffix(object, slashSeparator) {
return ObjectInfo{}, toObjectErr(traceError(errFileNotFound), bucket, object)
}
if err := checkGetObjArgs(bucket, object); err != nil { if err := checkGetObjArgs(bucket, object); err != nil {
return ObjectInfo{}, err return ObjectInfo{}, err
} }
@ -467,6 +461,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
if isObjectDir(object, size) { if isObjectDir(object, size) {
// Check if an object is present as one of the parent dir. // Check if an object is present as one of the parent dir.
// -- FIXME. (needs a new kind of lock). // -- FIXME. (needs a new kind of lock).
// -- FIXME (this also causes performance issue when disks are down).
if xl.parentDirIsObject(bucket, path.Dir(object)) { if xl.parentDirIsObject(bucket, path.Dir(object)) {
return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object) return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object)
} }
@ -480,6 +475,7 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io.
// Check if an object is present as one of the parent dir. // Check if an object is present as one of the parent dir.
// -- FIXME. (needs a new kind of lock). // -- FIXME. (needs a new kind of lock).
// -- FIXME (this also causes performance issue when disks are down).
if xl.parentDirIsObject(bucket, path.Dir(object)) { if xl.parentDirIsObject(bucket, path.Dir(object)) {
return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object) return ObjectInfo{}, toObjectErr(traceError(errFileAccessDenied), bucket, object)
} }

@ -73,9 +73,9 @@ func TestXLDeleteObjectBasic(t *testing.T) {
{".test", "obj", BucketNameInvalid{Bucket: ".test"}}, {".test", "obj", BucketNameInvalid{Bucket: ".test"}},
{"----", "obj", BucketNameInvalid{Bucket: "----"}}, {"----", "obj", BucketNameInvalid{Bucket: "----"}},
{"bucket", "", ObjectNameInvalid{Bucket: "bucket", Object: ""}}, {"bucket", "", ObjectNameInvalid{Bucket: "bucket", Object: ""}},
{"bucket", "obj/", ObjectNameInvalid{Bucket: "bucket", Object: "obj/"}},
{"bucket", "/obj", ObjectNameInvalid{Bucket: "bucket", Object: "/obj"}},
{"bucket", "doesnotexist", ObjectNotFound{Bucket: "bucket", Object: "doesnotexist"}}, {"bucket", "doesnotexist", ObjectNotFound{Bucket: "bucket", Object: "doesnotexist"}},
{"bucket", "obj/", ObjectNotFound{Bucket: "bucket", Object: "obj/"}},
{"bucket", "/obj", ObjectNotFound{Bucket: "bucket", Object: "/obj"}},
{"bucket", "obj", nil}, {"bucket", "obj", nil},
} }

Loading…
Cancel
Save