handle trimming '/' if present in the object names (#11765)

- MultipleDeletes should handle '/' prefix for objectnames
- Trimming the slash alone is enough for ListObjects()
  prefix and markers

fixes #11769
This commit is contained in:
Harshavardhana 2021-03-11 13:57:03 -08:00 committed by GitHub
parent 9b54fcdf12
commit feafccf007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 70 deletions

View file

@ -36,19 +36,8 @@ func getListObjectsV1Args(values url.Values) (prefix, marker, delimiter string,
maxkeys = maxObjectList
}
var err error
prefix, err = unescapePath(values.Get("prefix"))
if err != nil {
errCode = ErrInvalidRequest
return
}
marker, err = unescapePath(values.Get("marker"))
if err != nil {
errCode = ErrInvalidRequest
return
}
prefix = trimLeadingSlash(values.Get("prefix"))
marker = trimLeadingSlash(values.Get("marker"))
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")
return
@ -67,19 +56,8 @@ func getListBucketObjectVersionsArgs(values url.Values) (prefix, marker, delimit
maxkeys = maxObjectList
}
var err error
prefix, err = unescapePath(values.Get("prefix"))
if err != nil {
errCode = ErrInvalidRequest
return
}
marker, err = unescapePath(values.Get("key-marker"))
if err != nil {
errCode = ErrInvalidRequest
return
}
prefix = trimLeadingSlash(values.Get("prefix"))
marker = trimLeadingSlash(values.Get("key-marker"))
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")
versionIDMarker = values.Get("version-id-marker")
@ -108,19 +86,8 @@ func getListObjectsV2Args(values url.Values) (prefix, token, startAfter, delimit
maxkeys = maxObjectList
}
var err error
prefix, err = unescapePath(values.Get("prefix"))
if err != nil {
errCode = ErrInvalidRequest
return
}
startAfter, err = unescapePath(values.Get("start-after"))
if err != nil {
errCode = ErrInvalidRequest
return
}
prefix = trimLeadingSlash(values.Get("prefix"))
startAfter = trimLeadingSlash(values.Get("start-after"))
delimiter = values.Get("delimiter")
fetchOwner = values.Get("fetch-owner") == "true"
encodingType = values.Get("encoding-type")
@ -150,19 +117,8 @@ func getBucketMultipartResources(values url.Values) (prefix, keyMarker, uploadID
maxUploads = maxUploadsList
}
var err error
prefix, err = unescapePath(values.Get("prefix"))
if err != nil {
errCode = ErrInvalidRequest
return
}
keyMarker, err = unescapePath(values.Get("key-marker"))
if err != nil {
errCode = ErrInvalidRequest
return
}
prefix = trimLeadingSlash(values.Get("prefix"))
keyMarker = trimLeadingSlash(values.Get("key-marker"))
uploadIDMarker = values.Get("upload-id-marker")
delimiter = values.Get("delimiter")
encodingType = values.Get("encoding-type")

View file

@ -411,6 +411,11 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter,
return
}
// Convert object name delete objects if it has `/` in the beginning.
for i := range deleteObjects.Objects {
deleteObjects.Objects[i].ObjectName = trimLeadingSlash(deleteObjects.Objects[i].ObjectName)
}
// Call checkRequestAuthType to populate ReqInfo.AccessKey before GetBucketInfo()
// Ignore errors here to preserve the S3 error behavior of GetBucketInfo()
checkRequestAuthType(ctx, r, policy.DeleteObjectAction, bucket, "")
@ -853,13 +858,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
// by the filename attribute passed in multipart
formValues.Set("Key", strings.Replace(formValues.Get("Key"), "${filename}", fileName, -1))
}
object := formValues.Get("Key")
object, err = unescapePath(object)
if err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return
}
object := trimLeadingSlash(formValues.Get("Key"))
successRedirect := formValues.Get("success_action_redirect")
successStatus := formValues.Get("success_action_status")

View file

@ -687,6 +687,20 @@ func ceilFrac(numerator, denominator int64) (ceil int64) {
return
}
func trimLeadingSlash(ep string) string {
if len(ep) > 0 && ep[0] == '/' {
// Path ends with '/' preserve it
if ep[len(ep)-1] == '/' && len(ep) > 1 {
ep = path.Clean(ep)
ep += slashSeparator
} else {
ep = path.Clean(ep)
}
ep = ep[1:]
}
return ep
}
// unescapeGeneric is similar to url.PathUnescape or url.QueryUnescape
// depending on input, additionally also handles situations such as
// `//` are normalized as `/`, also removes any `/` prefix before
@ -696,17 +710,7 @@ func unescapeGeneric(p string, escapeFn func(string) (string, error)) (string, e
if err != nil {
return "", err
}
if len(ep) > 0 && ep[0] == '/' {
// Path ends with '/' preserve it
if ep[len(ep)-1] == '/' {
ep = path.Clean(ep)
ep += slashSeparator
} else {
ep = path.Clean(ep)
}
ep = ep[1:]
}
return ep, nil
return trimLeadingSlash(ep), nil
}
// unescapePath is similar to unescapeGeneric but for specifically