summaryrefslogtreecommitdiff
path: root/indra/llxml/llxmlnode.cpp
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2024-07-09 01:17:22 +0300
committerGitHub <noreply@github.com>2024-07-09 01:17:22 +0300
commita5a7c7c8f5b529f766147c06cfe834f2f0c5f74c (patch)
treec24d14ce8c535cca8dbdc576faf9ecc032c36f9a /indra/llxml/llxmlnode.cpp
parentcd5d35ddab52ae577e286140ee54664202a0091d (diff)
parentdb6fdcf2df62d1b2bef2bd0a9019b74663b8568c (diff)
Merge pull request #1949 from sldevel/xmlrpc-crash-fix
Fix for crash in XMLRPC reply decoding on login with large inventories
Diffstat (limited to 'indra/llxml/llxmlnode.cpp')
-rw-r--r--indra/llxml/llxmlnode.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 7f6b8093fc..d6f9a56c9d 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -38,7 +38,9 @@
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
+#include "llbase64.h"
#include "llquaternion.h"
+#include "llsd.h"
#include "llstring.h"
#include "lluuid.h"
#include "lldir.h"
@@ -3263,3 +3265,171 @@ S32 LLXMLNode::getLineNumber()
{
return mLineNumber;
}
+
+bool LLXMLNode::parseXmlRpcArrayValue(LLSD& target)
+{
+ LLXMLNode* datap = getFirstChild().get();
+ if (!datap)
+ {
+ LL_WARNS() << "No inner XML element." << LL_ENDL;
+ return false;
+ }
+ if (!datap->hasName("data"))
+ {
+ LL_WARNS() << "No inner XML element (<data> expected, got: "
+ << datap->mName->mString << ")" << LL_ENDL;
+ return false;
+ }
+ if (datap->getNextSibling().get())
+ {
+ LL_WARNS() << "Multiple inner XML elements (single <data> expected)"
+ << LL_ENDL;
+ return false;
+ }
+ for (LLXMLNode* itemp = datap->getFirstChild().get(); itemp;
+ itemp = itemp->getNextSibling().get())
+ {
+ LLSD value;
+ if (!itemp->fromXMLRPCValue(value))
+ {
+ return false;
+ }
+ target.append(value);
+ }
+ return true;
+}
+
+bool LLXMLNode::parseXmlRpcStructValue(LLSD& target)
+{
+ std::string name;
+ LLSD value;
+ for (LLXMLNode* itemp = getFirstChild().get(); itemp;
+ itemp = itemp->getNextSibling().get())
+ {
+ if (!itemp->hasName("member"))
+ {
+ LL_WARNS() << "Invalid inner XML element (<member> expected, got: <"
+ << itemp->mName->mString << ">" << LL_ENDL;
+ return false;
+ }
+ name.clear();
+ value.clear();
+ for (LLXMLNode* chilp = itemp->getFirstChild().get(); chilp;
+ chilp = chilp->getNextSibling().get())
+ {
+ if (chilp->hasName("name"))
+ {
+ name = LLStringFn::xml_decode(chilp->getTextContents());
+ }
+ else if (!chilp->fromXMLRPCValue(value))
+ {
+ return false;
+ }
+ }
+ if (name.empty())
+ {
+ LL_WARNS() << "Empty struct member name" << LL_ENDL;
+ return false;
+ }
+ target.insert(name, value);
+ }
+ return true;
+}
+
+bool LLXMLNode::fromXMLRPCValue(LLSD& target)
+{
+ target.clear();
+
+ if (!hasName("value"))
+ {
+ LL_WARNS() << "Invalid XML element (<value> expected), got: <"
+ << mName->mString << ">" << LL_ENDL;
+ return false;
+ }
+
+ LLXMLNode* childp = getFirstChild().get();
+ if (!childp)
+ {
+ LL_WARNS() << "No inner XML element (value type expected)" << LL_ENDL;
+ // Value with no type qualifier is treated as string
+ target.assign(LLStringFn::xml_decode(getTextContents()));
+ return true;
+ }
+
+ if (childp->getNextSibling())
+ {
+ LL_WARNS() << "Multiple inner XML elements (single expected)"
+ << LL_ENDL;
+ return false;
+ }
+
+ if (childp->hasName("string"))
+ {
+ target.assign(LLStringFn::xml_decode(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("int") || childp->hasName("i4"))
+ {
+ target.assign(std::stoi(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("double"))
+ {
+ target.assign(std::stod(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("boolean"))
+ {
+ target.assign(std::stoi(childp->getTextContents()) != 0);
+ return true;
+ }
+
+ if (childp->hasName("dateTime.iso8601"))
+ {
+ target.assign(LLSD::Date(childp->getTextContents()));
+ return true;
+ }
+
+ if (childp->hasName("base64"))
+ {
+ std::string decoded =
+ LLBase64::decodeAsString(inner->getTextContents());
+ size_t size = decoded.size();
+ LLSD::Binary binary(size);
+ if (size)
+ {
+ memcpy((void*)binary.data(), (void*)decoded.data(), size);
+ }
+ target.assign(binary);
+ return true;
+ }
+
+ if (childp->hasName("array"))
+ {
+ if (!childp->parseXmlRpcArrayValue(target))
+ {
+ target.clear();
+ return false;
+ }
+ return true;
+ }
+
+ if (childp->hasName("struct"))
+ {
+ if (!childp->parseXmlRpcStructValue(target))
+ {
+ target.clear();
+ return false;
+ }
+ return true;
+ }
+
+ LL_WARNS() << "Unknown inner XML element (known value type expected)"
+ << LL_ENDL;
+ // Value with unknown type qualifier is treated as string
+ target.assign(LLStringFn::xml_decode(childp->getTextContents()));
+ return true;
+}