From 8ee3b984ddde5614903623a5d53d4aee45540899 Mon Sep 17 00:00:00 2001 From: xirvik Date: Sat, 19 Sep 2026 02:23:52 +0000 Subject: [PATCH] Give network.xmlrpc.size_limit.set a floor A limit below any valid request rejects the request that would raise it again. --- src/rpc/rpc_manager.cc | 3 +++ src/rpc/rpc_manager.h | 4 ++++ test/Makefile.am | 4 +++- test/rpc/test_rpc_manager.cc | 21 +++++++++++++++++++++ test/rpc/test_rpc_manager.h | 17 +++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/rpc/test_rpc_manager.cc create mode 100644 test/rpc/test_rpc_manager.h diff --git a/src/rpc/rpc_manager.cc b/src/rpc/rpc_manager.cc index 39faf7a1..7778f4d1 100644 --- a/src/rpc/rpc_manager.cc +++ b/src/rpc/rpc_manager.cc @@ -172,6 +172,9 @@ RpcManager::set_size_limit(uint64_t size) { if (size > SCgiTask::max_content_size) throw torrent::input_error("XMLRPC size limit cannot exceed the SCGI content size limit."); + if (size < min_size_limit) + throw torrent::input_error("XMLRPC size limit is too small to hold a request."); + m_xmlrpc.set_size_limit(size); } diff --git a/src/rpc/rpc_manager.h b/src/rpc/rpc_manager.h index e9b84b8c..d20e1458 100644 --- a/src/rpc/rpc_manager.h +++ b/src/rpc/rpc_manager.h @@ -53,6 +53,10 @@ public: enum RPCType { XML, JSON }; + // A limit below the shortest useful request rejects every request, the one + // that would raise it again included. + static constexpr uint64_t min_size_limit = 1024; + RpcManager() = default; ~RpcManager() = default; diff --git a/test/Makefile.am b/test/Makefile.am index 7a4e35fe..cb4cd141 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -52,7 +52,9 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \ rpc/test_object_storage.cc \ rpc/test_object_storage.h \ rpc/test_parse_options.cc \ - rpc/test_parse_options.h + rpc/test_parse_options.h \ + rpc/test_rpc_manager.cc \ + rpc/test_rpc_manager.h rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \ src/test_command_dynamic.cc \ diff --git a/test/rpc/test_rpc_manager.cc b/test/rpc/test_rpc_manager.cc new file mode 100644 index 00000000..2bb5ea60 --- /dev/null +++ b/test/rpc/test_rpc_manager.cc @@ -0,0 +1,21 @@ +#include "config.h" + +#include "test/rpc/test_rpc_manager.h" + +#include + +#include "rpc/scgi_task.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(TestRpcManager); + +// A size limit too small to hold any request rejects every request, including +// the one that would put it back, so it can only be undone by a restart. +void +TestRpcManager::test_size_limit_bounds() { + CPPUNIT_ASSERT_THROW(m_rpc_manager.set_size_limit(0), torrent::input_error); + CPPUNIT_ASSERT_THROW(m_rpc_manager.set_size_limit(rpc::RpcManager::min_size_limit - 1), torrent::input_error); + CPPUNIT_ASSERT_THROW(m_rpc_manager.set_size_limit(rpc::SCgiTask::max_content_size + 1), torrent::input_error); + + CPPUNIT_ASSERT_NO_THROW(m_rpc_manager.set_size_limit(rpc::RpcManager::min_size_limit)); + CPPUNIT_ASSERT_NO_THROW(m_rpc_manager.set_size_limit(rpc::SCgiTask::max_content_size)); +} diff --git a/test/rpc/test_rpc_manager.h b/test/rpc/test_rpc_manager.h new file mode 100644 index 00000000..a2a116e2 --- /dev/null +++ b/test/rpc/test_rpc_manager.h @@ -0,0 +1,17 @@ +#include "test/helpers/test_fixture.h" + +#include "rpc/rpc_manager.h" + +class TestRpcManager : public test_fixture { + CPPUNIT_TEST_SUITE(TestRpcManager); + + CPPUNIT_TEST(test_size_limit_bounds); + + CPPUNIT_TEST_SUITE_END(); + +public: + void test_size_limit_bounds(); + +private: + rpc::RpcManager m_rpc_manager; +};