summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorHenri Beauchamp <sldev@free.fr>2024-07-08 23:18:02 +0200
committerHenri Beauchamp <sldev@free.fr>2024-07-08 23:18:02 +0200
commit989cfe2f70441fe02222d369e84118a94dc96890 (patch)
tree50f52d9c4b956ce41fe3d4e5df135aab78fdbfb1 /indra/llcommon
parent94a66b558401c77953c990a992a91c7b32493f82 (diff)
Fix for crash in XMLRPC reply decoding on login with large inventories
Commit 2ea5ac0c43e3e28d2b1774f5367d099271a1da32 introduced a crash bug due to the recursive construction of the XMLTreeNode wrapper class. The constructor of the said class typically recurses twice as many times as there are entries in the user's inventory list. This commit: - Moves the fromXMLRPCValue() method and its helper functions from the LLSD class/module to the LLXMLNode class, where it belongs, thus making LLSD::TreeNode (which was a wrapper class to avoid making llcommon dependant on llxml, which is still the case after this commit) totally moot; the fromXMLRPCValue() call is now done directly on the LLXMLNode. - Moves the XML and XMLRPC decoding code out of the HTTP coroutine LLXMLRPCTransaction::Handler (coroutines got an even smaller and fixed stack), and into LLXMLRPCTransaction::Impl::process(). - Removes XMLTreeNode entirely, fixing the crash as a result.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llsd.cpp147
-rw-r--r--indra/llcommon/llsd.h10
2 files changed, 0 insertions, 157 deletions
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 2bbe06e72f..77fe545c3f 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -1018,153 +1018,6 @@ const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef();
LLSD::String LLSD::asXMLRPCValue() const { return "<value>" + safe(impl).asXMLRPCValue() + "</value>"; }
-static bool inline check(bool condition, const char* warning_message)
-{
- if (!condition)
- {
- LL_WARNS() << warning_message << LL_ENDL;
- }
-
- return condition;
-}
-
-static bool parseXMLRPCArrayValue(LLSD& target, LLSD::TreeNode* node)
-{
- LLSD::TreeNode* data = node->getFirstChild();
- if (!check(data, "No array inner XML element (<data> expected)") ||
- !check(data->hasName("data"), "Invalid array inner XML element (<data> expected)") ||
- !check(!data->getNextSibling(), "Multiple array inner XML elements (single <data> expected)"))
- return false;
-
- for (LLSD::TreeNode* item = data->getFirstChild(); item; item = item->getNextSibling())
- {
- LLSD value;
- if (!value.fromXMLRPCValue(item))
- return false;
-
- target.append(value);
- }
-
- return true;
-}
-
-static bool parseXMLRPCStructValue(LLSD& target, LLSD::TreeNode* node)
-{
- for (LLSD::TreeNode* item = node->getFirstChild(); item; item = item->getNextSibling())
- {
- if (!check(item->hasName("member"), "Invalid struct inner XML element (<member> expected)"))
- return false;
-
- std::string name;
- LLSD value;
- for (LLSD::TreeNode* subitem = item->getFirstChild(); subitem; subitem = subitem->getNextSibling())
- {
- if (subitem->hasName("name"))
- {
- name = LLStringFn::xml_decode(subitem->getTextContents());
- }
- else if (!value.fromXMLRPCValue(subitem))
- {
- return false;
- }
- }
- if (!check(!name.empty(), "Empty struct member name"))
- return false;
-
- target.insert(name, value);
- }
-
- return true;
-}
-
-bool LLSD::fromXMLRPCValue(TreeNode* node)
-{
- clear();
-
- llassert(node);
- if (!node)
- return false;
-
- if (!check(node->hasName("value"), "Invalid XML element (<value> expected)"))
- return false;
-
- TreeNode* inner = node->getFirstChild();
- if (!inner)
- {
- check(false, "No inner XML element (value type expected)");
- // Value with no type qualifier is treated as string
- assign(LLStringFn::xml_decode(node->getTextContents()));
- return true;
- }
-
- if (!check(!inner->getNextSibling(), "Multiple inner XML elements (single expected)"))
- return false;
-
- if (inner->hasName("string"))
- {
- assign(LLStringFn::xml_decode(inner->getTextContents()));
- return true;
- }
-
- if (inner->hasName("int") || inner->hasName("i4"))
- {
- assign(std::stoi(inner->getTextContents()));
- return true;
- }
-
- if (inner->hasName("double"))
- {
- assign(std::stod(inner->getTextContents()));
- return true;
- }
-
- if (inner->hasName("boolean"))
- {
- assign(!!std::stoi(inner->getTextContents()));
- return true;
- }
-
- if (inner->hasName("dateTime.iso8601"))
- {
- assign(Date(inner->getTextContents()));
- return true;
- }
-
- if (inner->hasName("base64"))
- {
- std::string decoded = LLBase64::decodeAsString(inner->getTextContents());
- Binary binary(decoded.size());
- memcpy(binary.data(), decoded.data(), decoded.size());
- assign(binary);
- return true;
- }
-
- if (inner->hasName("array"))
- {
- if (!parseXMLRPCArrayValue(*this, inner))
- {
- clear();
- return false;
- }
- return true;
- }
-
- if (inner->hasName("struct"))
- {
- if (!parseXMLRPCStructValue(*this, inner))
- {
- clear();
- return false;
- }
- return true;
- }
-
- check(false, "Unknown inner XML element (known value type expected)");
- // Value with unknown type qualifier is treated as string
- assign(LLStringFn::xml_decode(inner->getTextContents()));
- return true;
-}
-
// const char * helpers
LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
void LLSD::assign(const char* v)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 781e8d58e9..d2b3548831 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -290,16 +290,6 @@ public:
// See http://xmlrpc.com/spec.md
String asXMLRPCValue() const;
- struct TreeNode
- {
- virtual bool hasName(const String& name) const = 0;
- virtual String getTextContents() const = 0;
- virtual TreeNode* getFirstChild() const = 0;
- virtual TreeNode* getNextSibling() const = 0;
- };
-
- bool fromXMLRPCValue(TreeNode* node);
-
operator Boolean() const { return asBoolean(); }
operator Integer() const { return asInteger(); }
operator Real() const { return asReal(); }