mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-14 22:22:31 +00:00
Do not dereference missing text nodes in the tinyxml2 backend.
Empty elements and element children crashed the parser on a null.
This commit is contained in:
@@ -49,13 +49,23 @@ element_access(const tinyxml2::XMLElement* elem, std::initializer_list<std::stri
|
||||
return result;
|
||||
}
|
||||
|
||||
const char*
|
||||
element_text_value(const tinyxml2::XMLNode* node) {
|
||||
auto text = node->ToText();
|
||||
|
||||
if (text == nullptr)
|
||||
throw rpc_error(XMLRPC_TYPE_ERROR, "expected a text value");
|
||||
|
||||
return text->Value();
|
||||
}
|
||||
|
||||
long long
|
||||
element_to_int(const tinyxml2::XMLNode* elem) {
|
||||
char* pos;
|
||||
if (elem->FirstChild() == nullptr) {
|
||||
throw rpc_error(XMLRPC_TYPE_ERROR, "unable to parse empty integer");
|
||||
}
|
||||
auto str = elem->FirstChild()->ToText()->Value();
|
||||
auto str = element_text_value(elem->FirstChild());
|
||||
auto result = std::strtoll(str, &pos, 10);
|
||||
if (pos == str || *pos != '\0')
|
||||
throw rpc_error(XMLRPC_TYPE_ERROR, "unable to parse integer value");
|
||||
@@ -85,7 +95,7 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
|
||||
if (child_element == nullptr)
|
||||
return torrent::Object("");
|
||||
|
||||
return torrent::Object(child_element->ToText()->Value());
|
||||
return torrent::Object(element_text_value(child_element));
|
||||
|
||||
} else if (std::strncmp(root_type, "int", sizeof("int")) == 0 ||
|
||||
std::strncmp(root_type, "i4", sizeof("i4")) == 0 ||
|
||||
@@ -98,7 +108,7 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
|
||||
if (child_element == nullptr)
|
||||
throw rpc_error(XMLRPC_TYPE_ERROR, "empty boolean element");
|
||||
|
||||
auto boolean_text = std::string(child_element->ToText()->Value());
|
||||
auto boolean_text = std::string(element_text_value(child_element));
|
||||
|
||||
if (boolean_text == "1")
|
||||
return torrent::Object((int64_t)1);
|
||||
@@ -129,7 +139,12 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
|
||||
if (name_element == nullptr)
|
||||
throw rpc_error(XMLRPC_PARSE_ERROR, "struct member missing name element");
|
||||
|
||||
map[name_element->GetText()] = std::move(xml_value_to_object(child->FirstChildElement("value")));
|
||||
auto name_text = name_element->GetText();
|
||||
|
||||
if (name_text == nullptr)
|
||||
throw rpc_error(XMLRPC_PARSE_ERROR, "struct member has an empty name element");
|
||||
|
||||
map[name_text] = std::move(xml_value_to_object(child->FirstChildElement("value")));
|
||||
}
|
||||
|
||||
return map_raw;
|
||||
@@ -140,7 +155,7 @@ xml_value_to_object(const tinyxml2::XMLNode* elem) {
|
||||
if (child_element == nullptr)
|
||||
return torrent::Object("");
|
||||
|
||||
return torrent::Object(utils::decode_base64(utils::remove_newlines(child_element->ToText()->Value())));
|
||||
return torrent::Object(utils::decode_base64(utils::remove_newlines(element_text_value(child_element))));
|
||||
|
||||
} else {
|
||||
throw rpc_error(XMLRPC_INTERNAL_ERROR, "received unsupported value type: " + std::string(root_type));
|
||||
@@ -300,6 +315,9 @@ process_document(const tinyxml2::XMLDocument* doc, tinyxml2::XMLPrinter* printer
|
||||
if (doc->FirstChildElement("methodCall")->FirstChildElement("methodName") == nullptr)
|
||||
throw rpc_error(XMLRPC_PARSE_ERROR, "methodName element not found");
|
||||
auto method_name = doc->FirstChildElement("methodCall")->FirstChildElement("methodName")->GetText();
|
||||
|
||||
if (method_name == nullptr)
|
||||
throw rpc_error(XMLRPC_PARSE_ERROR, "methodName element is empty");
|
||||
torrent::Object result;
|
||||
|
||||
// Add a shim here for system.multicall to allow better code reuse, and
|
||||
@@ -310,6 +328,9 @@ process_document(const tinyxml2::XMLDocument* doc, tinyxml2::XMLPrinter* printer
|
||||
auto parent_elements = element_access(doc->RootElement(), {"params", "param", "value", "array", "data"});
|
||||
for (auto child = parent_elements->FirstChildElement("value"); child; child = child->NextSiblingElement("value")) {
|
||||
auto sub_method_name = element_access(child, {"struct", "member", "value", "string"})->GetText();
|
||||
|
||||
if (sub_method_name == nullptr)
|
||||
throw rpc_error(XMLRPC_PARSE_ERROR, "multicall methodName element is empty");
|
||||
// If sub_params ends up a nullptr at the end of this if-chian,
|
||||
// execute_command will turn it into an empty list
|
||||
auto sub_params = element_access(child, {"struct", "member"});
|
||||
|
||||
Reference in New Issue
Block a user