From 3055a67cc20f1e461f5f1a26cb1522b7e88c79f9 Mon Sep 17 00:00:00 2001 From: Matt Benjamin Date: Tue, 26 Jun 2018 17:40:48 -0400 Subject: [PATCH] rgw: escape markers in RGWOp_Metadata_List::execute Fixes: http://tracker.ceph.com/issues/23099 Signed-off-by: Matt Benjamin --- src/rgw/rgw_common.cc | 53 +++--------------------------------- src/rgw/rgw_common.h | 48 ++++++++++++++++++++++++++++++++ src/rgw/rgw_rest_metadata.cc | 31 +++++++++++++++++++-- 3 files changed, 80 insertions(+), 52 deletions(-) diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index bdeb7aa45aa..6fdea97419b 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -1740,56 +1740,11 @@ bool RGWUserCaps::is_valid_cap_type(const string& tp) return false; } -static ssize_t unescape_str(const string& s, ssize_t ofs, char esc_char, char special_char, string *dest) -{ - const char *src = s.c_str(); - char dest_buf[s.size() + 1]; - char *destp = dest_buf; - bool esc = false; - - dest_buf[0] = '\0'; - - for (size_t i = ofs; i < s.size(); i++) { - char c = src[i]; - if (!esc && c == esc_char) { - esc = true; - continue; - } - if (!esc && c == special_char) { - *destp = '\0'; - *dest = dest_buf; - return (ssize_t)i + 1; - } - *destp++ = c; - esc = false; - } - *destp = '\0'; - *dest = dest_buf; - return string::npos; -} - -static void escape_str(const string& s, char esc_char, char special_char, string *dest) -{ - const char *src = s.c_str(); - char dest_buf[s.size() * 2 + 1]; - char *destp = dest_buf; - - for (size_t i = 0; i < s.size(); i++) { - char c = src[i]; - if (c == esc_char || c == special_char) { - *destp++ = esc_char; - } - *destp++ = c; - } - *destp++ = '\0'; - *dest = dest_buf; -} - void rgw_pool::from_str(const string& s) { - size_t pos = unescape_str(s, 0, '\\', ':', &name); + size_t pos = rgw_unescape_str(s, 0, '\\', ':', &name); if (pos != string::npos) { - pos = unescape_str(s, pos, '\\', ':', &ns); + pos = rgw_unescape_str(s, pos, '\\', ':', &ns); /* ignore return; if pos != string::npos it means that we had a colon * in the middle of ns that wasn't escaped, we're going to stop there */ @@ -1799,12 +1754,12 @@ void rgw_pool::from_str(const string& s) string rgw_pool::to_str() const { string esc_name; - escape_str(name, '\\', ':', &esc_name); + rgw_escape_str(name, '\\', ':', &esc_name); if (ns.empty()) { return esc_name; } string esc_ns; - escape_str(ns, '\\', ':', &esc_ns); + rgw_escape_str(ns, '\\', ':', &esc_ns); return esc_name + ":" + esc_ns; } diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index d5c0e7e15d7..86141c725af 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -2400,4 +2400,52 @@ extern string lowercase_dash_http_attr(const string& orig); void rgw_setup_saved_curl_handles(); void rgw_release_all_curl_handles(); +static inline void rgw_escape_str(const string& s, char esc_char, + char special_char, string *dest) +{ + const char *src = s.c_str(); + char dest_buf[s.size() * 2 + 1]; + char *destp = dest_buf; + + for (size_t i = 0; i < s.size(); i++) { + char c = src[i]; + if (c == esc_char || c == special_char) { + *destp++ = esc_char; + } + *destp++ = c; + } + *destp++ = '\0'; + *dest = dest_buf; +} + +static inline ssize_t rgw_unescape_str(const string& s, ssize_t ofs, + char esc_char, char special_char, + string *dest) +{ + const char *src = s.c_str(); + char dest_buf[s.size() + 1]; + char *destp = dest_buf; + bool esc = false; + + dest_buf[0] = '\0'; + + for (size_t i = ofs; i < s.size(); i++) { + char c = src[i]; + if (!esc && c == esc_char) { + esc = true; + continue; + } + if (!esc && c == special_char) { + *destp = '\0'; + *dest = dest_buf; + return (ssize_t)i + 1; + } + *destp++ = c; + esc = false; + } + *destp = '\0'; + *dest = dest_buf; + return string::npos; +} + #endif diff --git a/src/rgw/rgw_rest_metadata.cc b/src/rgw/rgw_rest_metadata.cc index 14056edb389..c3835cd1633 100644 --- a/src/rgw/rgw_rest_metadata.cc +++ b/src/rgw/rgw_rest_metadata.cc @@ -20,6 +20,7 @@ #include "rgw_client_io.h" #include "common/errno.h" #include "common/strtol.h" +#include "rgw/rgw_b64.h" #include "include/assert.h" #define dout_context g_ceph_context @@ -69,9 +70,25 @@ void RGWOp_Metadata_Get_Myself::execute() { } void RGWOp_Metadata_List::execute() { - string marker = s->info.args.get("marker"); + string marker; + ldout(s->cct, 16) << __func__ + << " raw marker " << s->info.args.get("marker") + << dendl; + + try { + marker = s->info.args.get("marker"); + if (!marker.empty()) { + marker = rgw::from_base64(marker); + } + ldout(s->cct, 16) << __func__ + << " marker " << marker << dendl; + } catch (...) { + marker = std::string(""); + } + bool max_entries_specified; - string max_entries_str = s->info.args.get("max-entries", &max_entries_specified); + string max_entries_str = + s->info.args.get("max-entries", &max_entries_specified); bool extended_response = (max_entries_specified); /* for backward compatibility, if max-entries is not specified we will send the old response format */ @@ -94,6 +111,12 @@ void RGWOp_Metadata_List::execute() { void *handle; int max = 1000; + /* example markers: + marker = "3:b55a9110:root::bu_9:head"; + marker = "3:b9a8b2a6:root::sorry_janefonda_890:head"; + marker = "3:bf885d8f:root::sorry_janefonda_665:head"; + */ + http_ret = store->meta_mgr->list_keys_init(metadata_key, marker, &handle); if (http_ret < 0) { dout(5) << "ERROR: can't get key: " << cpp_strerror(http_ret) << dendl; @@ -134,7 +157,9 @@ void RGWOp_Metadata_List::execute() { encode_json("truncated", truncated, s->formatter); encode_json("count", count, s->formatter); if (truncated) { - encode_json("marker", store->meta_mgr->get_marker(handle), s->formatter); + string esc_marker = + rgw::to_base64(store->meta_mgr->get_marker(handle)); + encode_json("marker", esc_marker, s->formatter); } s->formatter->close_section(); }