From feafccf0072a9b5fbddc33553890ff56cb2f83b6 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 11 Mar 2021 13:57:03 -0800 Subject: [PATCH] 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 --- cmd/api-resources.go | 60 ++++++------------------------------------ cmd/bucket-handlers.go | 13 +++++---- cmd/utils.go | 26 ++++++++++-------- 3 files changed, 29 insertions(+), 70 deletions(-) diff --git a/cmd/api-resources.go b/cmd/api-resources.go index 74d3eeff8..6313f87aa 100644 --- a/cmd/api-resources.go +++ b/cmd/api-resources.go @@ -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") diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 46fe06152..2ab18cf44 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -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") diff --git a/cmd/utils.go b/cmd/utils.go index 5834630a8..0d1322369 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -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