From 2f6755968475746955ea42e3b4d378e49a6acdfc Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sun, 27 Dec 2015 23:00:36 -0800 Subject: [PATCH] handlers: read ContentLength value directly from http.Request. Do not look for Content-Length in headers and try to convert them into integer representations use ContentLength field from *http.Request*. If Content-Length is understood to be as '-1' then treat it as an error condition, since it could be a malformed body to crash the server. Fixes #1011 --- bucket-handlers.go | 9 ++++----- object-handlers.go | 45 ++++++++++++--------------------------------- utils.go | 11 +++-------- 3 files changed, 19 insertions(+), 46 deletions(-) diff --git a/bucket-handlers.go b/bucket-handlers.go index 9a4cf64c9..14c929ef7 100644 --- a/bucket-handlers.go +++ b/bucket-handlers.go @@ -226,8 +226,8 @@ func (api CloudStorageAPI) PutBucketHandler(w http.ResponseWriter, req *http.Req // if body of request is non-nil then check for validity of Content-Length if req.Body != nil { - /// if Content-Length missing, deny the request - if req.Header.Get("Content-Length") == "" { + /// if Content-Length is unknown/missing, deny the request + if req.ContentLength == -1 { writeErrorResponse(w, req, MissingContentLength, req.URL.Path) return } @@ -275,9 +275,8 @@ func (api CloudStorageAPI) PutBucketHandler(w http.ResponseWriter, req *http.Req func (api CloudStorageAPI) PostPolicyBucketHandler(w http.ResponseWriter, req *http.Request) { // if body of request is non-nil then check for validity of Content-Length if req.Body != nil { - /// if Content-Length missing, deny the request - size := req.Header.Get("Content-Length") - if size == "" { + /// if Content-Length is unknown/missing, deny the request + if req.ContentLength == -1 { writeErrorResponse(w, req, MissingContentLength, req.URL.Path) return } diff --git a/object-handlers.go b/object-handlers.go index f285d57c9..53443b14a 100644 --- a/object-handlers.go +++ b/object-handlers.go @@ -140,9 +140,9 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, req *http.Req writeErrorResponse(w, req, InvalidDigest, req.URL.Path) return } - /// if Content-Length missing, deny the request - size := req.Header.Get("Content-Length") - if size == "" { + /// if Content-Length is unknown/missing, deny the request + size := req.ContentLength + if size == -1 { writeErrorResponse(w, req, MissingContentLength, req.URL.Path) return } @@ -151,16 +151,6 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, req *http.Req writeErrorResponse(w, req, EntityTooLarge, req.URL.Path) return } - var sizeInt64 int64 - { - var err error - sizeInt64, err = strconv.ParseInt(size, 10, 64) - if err != nil { - errorIf(probe.NewError(err), "Parsing Content-Length failed.", nil) - writeErrorResponse(w, req, InvalidRequest, req.URL.Path) - return - } - } var signature *fs.Signature if !api.Anonymous { @@ -176,7 +166,7 @@ func (api CloudStorageAPI) PutObjectHandler(w http.ResponseWriter, req *http.Req } } - metadata, err := api.Filesystem.CreateObject(bucket, object, md5, sizeInt64, req.Body, signature) + metadata, err := api.Filesystem.CreateObject(bucket, object, md5, size, req.Body, signature) if err != nil { errorIf(err.Trace(), "CreateObject failed.", nil) switch err.ToGoError().(type) { @@ -265,13 +255,6 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, req *http } } - /// if Content-Length missing, throw away - size := req.Header.Get("Content-Length") - if size == "" { - writeErrorResponse(w, req, MissingContentLength, req.URL.Path) - return - } - // get Content-MD5 sent by client and verify if valid md5 := req.Header.Get("Content-MD5") if !isValidMD5(md5) { @@ -279,23 +262,19 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, req *http return } + /// if Content-Length is unknown/missing, throw away + size := req.ContentLength + if size == -1 { + writeErrorResponse(w, req, MissingContentLength, req.URL.Path) + return + } + /// maximum Upload size for multipart objects in a single operation if isMaxObjectSize(size) { writeErrorResponse(w, req, EntityTooLarge, req.URL.Path) return } - var sizeInt64 int64 - { - var err error - sizeInt64, err = strconv.ParseInt(size, 10, 64) - if err != nil { - errorIf(probe.NewError(err), "Parsing Content-Length failed.", nil) - writeErrorResponse(w, req, InvalidRequest, req.URL.Path) - return - } - } - uploadID := req.URL.Query().Get("uploadId") partIDString := req.URL.Query().Get("partNumber") @@ -323,7 +302,7 @@ func (api CloudStorageAPI) PutObjectPartHandler(w http.ResponseWriter, req *http } } - calculatedMD5, err := api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, sizeInt64, req.Body, signature) + calculatedMD5, err := api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, req.Body, signature) if err != nil { errorIf(err.Trace(), "CreateObjectPart failed.", nil) switch err.ToGoError().(type) { diff --git a/utils.go b/utils.go index 467692bff..f7a4ca7c1 100644 --- a/utils.go +++ b/utils.go @@ -18,7 +18,6 @@ package main import ( "encoding/base64" - "strconv" "strings" ) @@ -36,17 +35,13 @@ func isValidMD5(md5 string) bool { /// http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadingObjects.html const ( - // maximum object size per PUT request is 5GB + // maximum object size per PUT request is 5GiB maxObjectSize = 1024 * 1024 * 1024 * 5 ) // isMaxObjectSize - verify if max object size -func isMaxObjectSize(size string) bool { - i, err := strconv.ParseInt(size, 10, 64) - if err != nil { - return true - } - if i > maxObjectSize { +func isMaxObjectSize(size int64) bool { + if size > maxObjectSize { return true } return false