From a7e80e2b02e74361f51d9dba43c6126f4728b20b Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 14 May 2013 22:04:08 -0700 Subject: [PATCH] rgw: a function to read all request input Factor out this useful function. Also make sure that we never read more than a specified (large enough) max. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_rest.cc | 51 ++++++++++++++++++++++++++++++++------------- src/rgw/rgw_rest.h | 2 ++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 3c70b84ea62bc..b7c8e69ea0cae 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -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() diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index ce474b0d6d55f..e3b20bd716046 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -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); -- 2.39.5