diff --git a/src/rpc/xmlrpc.h b/src/rpc/xmlrpc.h index 5e112b5e..47b1a283 100644 --- a/src/rpc/xmlrpc.h +++ b/src/rpc/xmlrpc.h @@ -37,6 +37,8 @@ #ifndef RTORRENT_RPC_XMLRPC_H #define RTORRENT_RPC_XMLRPC_H +#include "scgi_task.h" + #include #include @@ -74,7 +76,7 @@ public: static const int call_file = 5; static const int call_file_itr = 6; - XmlRpc() : m_env(NULL), m_registry(NULL), m_dialect(dialect_i8) {} + XmlRpc() : m_env(NULL), m_registry(NULL), m_dialect(dialect_i8), m_sizeLimit(SCgiTask::max_content_size) {} bool is_valid() const; @@ -97,17 +99,21 @@ public: void set_size_limit(uint64_t size); private: + slot_download m_slotFindDownload; + slot_file m_slotFindFile; + slot_tracker m_slotFindTracker; + slot_peer m_slotFindPeer; + + // Only used by xmlrpc-c void* m_env; void* m_registry; int m_dialect; + // Only used by tinyxml2 bool m_isValid; + uint64_t m_sizeLimit; - slot_download m_slotFindDownload; - slot_file m_slotFindFile; - slot_tracker m_slotFindTracker; - slot_peer m_slotFindPeer; }; } diff --git a/src/rpc/xmlrpc_tinyxml2.cc b/src/rpc/xmlrpc_tinyxml2.cc index ca15e51b..c81d33a1 100644 --- a/src/rpc/xmlrpc_tinyxml2.cc +++ b/src/rpc/xmlrpc_tinyxml2.cc @@ -423,6 +423,11 @@ print_xmlrpc_fault(int faultCode, std::string faultString, tinyxml2::XMLPrinter* bool XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { + if (length > m_sizeLimit) { + tinyxml2::XMLPrinter printer(nullptr, true, 0); + print_xmlrpc_fault(XMLRPC_LIMIT_EXCEEDED_ERROR, "Content size exceeds maximum XML-RPC limit", &printer); + return slotWrite(printer.CStr(), printer.CStrSize()-1); + } tinyxml2::XMLDocument doc; doc.Parse(inBuffer, length); try { @@ -449,8 +454,8 @@ void XmlRpc::cleanup() {} void XmlRpc::insert_command(const char*, const char*, const char*) {} void XmlRpc::set_dialect(int) {} -int64_t XmlRpc::size_limit() { return std::numeric_limits::max(); } -void XmlRpc::set_size_limit(uint64_t) {} +int64_t XmlRpc::size_limit() { return m_sizeLimit; } +void XmlRpc::set_size_limit(uint64_t limit) { m_sizeLimit = limit; } bool XmlRpc::is_valid() const { return m_isValid; } diff --git a/test/rpc/xmlrpc_test.cc b/test/rpc/xmlrpc_test.cc index 89d10f60..241ab2e7 100644 --- a/test/rpc/xmlrpc_test.cc +++ b/test/rpc/xmlrpc_test.cc @@ -57,7 +57,7 @@ XmlrpcTest::test_basics() { // Sanity check the above parser CPPUNIT_ASSERT_MESSAGE("Could not parse test data", inputs.size() > 0 && inputs.size() == outputs.size() && inputs.size() == titles.size()); for (int i = 0; i < inputs.size(); i++) { - auto output = std::string(""); + std::string output; m_xmlrpc.process(inputs[i].c_str(), inputs[i].size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL_MESSAGE(titles[i], std::string(outputs[i]), output); } @@ -70,12 +70,23 @@ XmlrpcTest::test_invalid_utf8() { // just a series of bytes so it reflects just fine. std::string input = "xmlrpc_reflect\xc3\x28"; std::string expected = "\xc3\x28"; - auto output = std::string(""); + std::string output; + m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); + CPPUNIT_ASSERT_EQUAL(expected, output); +} + +void +XmlrpcTest::test_size_limit() { + std::string input = "xmlrpc_reflect\xc3\x28"; + std::string expected = "faultCode-509faultStringContent size exceeds maximum XML-RPC limit"; + std::string output; + m_xmlrpc.set_size_limit(1); m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL(expected, output); } #else void XmlrpcTest::test_invalid_utf8() {} void XmlrpcTest::test_basics() {} +void XmlrpcTest::test_size_limit() {} void XmlrpcTest::setUp() {} #endif diff --git a/test/rpc/xmlrpc_test.h b/test/rpc/xmlrpc_test.h index ff1d1ab3..9f9312e0 100644 --- a/test/rpc/xmlrpc_test.h +++ b/test/rpc/xmlrpc_test.h @@ -7,6 +7,7 @@ class XmlrpcTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(XmlrpcTest); CPPUNIT_TEST(test_basics); CPPUNIT_TEST(test_invalid_utf8); + CPPUNIT_TEST(test_size_limit); CPPUNIT_TEST_SUITE_END(); public: @@ -17,6 +18,7 @@ public: void test_basics(); void test_invalid_utf8(); + void test_size_limit(); private: rpc::XmlRpc m_xmlrpc;