From 342e94261f541a261bebf2aa2814431fb4d52d2c Mon Sep 17 00:00:00 2001 From: Ernest Zaslavsky Date: Tue, 15 Jul 2025 17:24:25 +0300 Subject: [PATCH] s3_client: parse multipart response XML defensively Ensure robust handling of XML responses when initiating multipart uploads. Check for the existence of required nodes before access, and throw an exception if the XML is empty or malformed. Refs: https://github.com/scylladb/scylladb/issues/24676 Closes scylladb/scylladb#24990 --- utils/s3/client.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/utils/s3/client.cc b/utils/s3/client.cc index 733c42065e..da52797ae8 100644 --- a/utils/s3/client.cc +++ b/utils/s3/client.cc @@ -711,6 +711,14 @@ public: }; sstring parse_multipart_upload_id(sstring& body) { + auto get_node_safe = [](const T* node, const std::string_view node_name) { + auto child = node->first_node(node_name.data()); + if (!child) { + throw std::runtime_error(seastar::format("'{}' node is missing in InitiateMultipartUploadResult response", node_name)); + } + return child; + }; + auto doc = std::make_unique>(); try { doc->parse<0>(body.data()); @@ -720,8 +728,8 @@ sstring parse_multipart_upload_id(sstring& body) { // and handle the error the way it prefers return ""; } - auto root_node = doc->first_node("InitiateMultipartUploadResult"); - auto uploadid_node = root_node->first_node("UploadId"); + auto root_node = get_node_safe(doc.get(), "InitiateMultipartUploadResult"); + auto uploadid_node = get_node_safe(root_node, "UploadId"); return uploadid_node->value(); }