]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: a function to read all request input
authorYehuda Sadeh <yehuda@inktank.com>
Wed, 15 May 2013 05:04:08 +0000 (22:04 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Wed, 15 May 2013 05:04:08 +0000 (22:04 -0700)
Factor out this useful function. Also make sure that
we never read more than a specified (large enough) max.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h

index 3c70b84ea62bcf3adab5264f88bc734cc319ad51..b7c8e69ea0caec851594b142726559df63ae6482 100644 (file)
@@ -753,7 +753,7 @@ int RGWPutCORS_ObjStore::get_params()
   return ret;
 }
 
-static int read_all_chunked_input(req_state *s, char **pdata, int *plen)
+static int read_all_chunked_input(req_state *s, char **pdata, int *plen, int max_read)
 {
 #define READ_CHUNK 4096
 #define MAX_READ_CHUNK (128 * 1024)
@@ -777,6 +777,10 @@ static int read_all_chunked_input(req_state *s, char **pdata, int *plen)
       if (need_to_read < MAX_READ_CHUNK)
        need_to_read *= 2;
 
+      if (total > max_read) {
+        free(data);
+        return -ERANGE;
+      }
       total += need_to_read;
 
       void *p = realloc(data, total + 1);
@@ -798,39 +802,58 @@ static int read_all_chunked_input(req_state *s, char **pdata, int *plen)
   return 0;
 }
 
-int RGWCompleteMultipart_ObjStore::get_params()
+int rgw_rest_read_all_input(struct req_state *s, char **pdata, int *plen, int max_len)
 {
-  upload_id = s->args.get("uploadId");
-
-  if (upload_id.empty()) {
-    ret = -ENOTSUP;
-    return ret;
-  }
   size_t cl = 0;
+  int len = 0;
+  char *data = NULL;
 
   if (s->length)
     cl = atoll(s->length);
   if (cl) {
+    if (cl > (size_t)max_len) {
+      return -ERANGE;
+    }
     data = (char *)malloc(cl + 1);
     if (!data) {
-       ret = -ENOMEM;
-       return ret;
+       return -ENOMEM;
     }
-    ret = s->cio->read(data, cl, &len);
+    int ret = s->cio->read(data, cl, &len);
     if (ret < 0)
       return ret;
     data[len] = '\0';
-  } else {
+  } else if (!s->length) {
     const char *encoding = s->env->get("HTTP_TRANSFER_ENCODING");
     if (!encoding || strcmp(encoding, "chunked") != 0)
       return -ERR_LENGTH_REQUIRED;
 
-    ret = read_all_chunked_input(s, &data, &len);
+    int ret = read_all_chunked_input(s, &data, &len, max_len);
     if (ret < 0)
       return ret;
   }
 
-  return ret;
+  *plen = len;
+  *pdata = data;
+
+  return 0;
+}
+
+
+int RGWCompleteMultipart_ObjStore::get_params()
+{
+  upload_id = s->args.get("uploadId");
+
+  if (upload_id.empty()) {
+    ret = -ENOTSUP;
+    return ret;
+  }
+
+#define COMPLETE_MULTIPART_MAX_LEN (1024 * 1024) /* api defines max 10,000 parts, this should be enough */
+  ret = rgw_rest_read_all_input(s, &data, &len, COMPLETE_MULTIPART_MAX_LEN);
+  if (ret < 0)
+    return ret;
+
+  return 0;
 }
 
 int RGWListMultipart_ObjStore::get_params()
index ce474b0d6d55f14961f0dd6eda79e8866ddd81b1..e3b20bd7160460c7015d13ffa8e4105515cd07db 100644 (file)
@@ -16,6 +16,8 @@ extern void rgw_flush_formatter_and_reset(struct req_state *s,
 extern void rgw_flush_formatter(struct req_state *s,
                                          ceph::Formatter *formatter);
 
+extern int rgw_rest_read_all_input(struct req_state *s, char **data, int *plen, int max_len);
+
 class RESTArgs {
 public:
   static int get_string(struct req_state *s, const string& name, const string& def_val, string *val, bool *existed = NULL);