From 9d7443f467147d1784fb7516d2a882db1abb5a8b Mon Sep 17 00:00:00 2001 From: arvidn Date: Sat, 25 Jan 2025 01:24:41 +0100 Subject: [PATCH] validate add_torrent_params::save_path at run-time --- ChangeLog | 1 + include/libtorrent/error_code.hpp | 2 ++ include/libtorrent/session_handle.hpp | 6 ++++++ src/error_code.cpp | 2 +- src/session_handle.cpp | 21 ++++++++++++++++++++- test/test_session.cpp | 17 +++++++++++++++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5b1ea0ef1cf..c98ab023de6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2.0.11 released + * validate add_torrent_params::save_path at run-time * use stricter rules for what filenames are valid on Android * fix applying IP filter to DHT traffic (HanabishiRecca) * fix race condition when cancelling requests after becoming a seed diff --git a/include/libtorrent/error_code.hpp b/include/libtorrent/error_code.hpp index 34497865040..d34ab0e3887 100644 --- a/include/libtorrent/error_code.hpp +++ b/include/libtorrent/error_code.hpp @@ -389,6 +389,8 @@ namespace errors { // specifying the flag to only save when there's anything new to save // (torrent_handle::only_if_modified) and there wasn't anything changed. resume_data_not_modified, + // the save_path in add_torrent_params is not valid + invalid_save_path, // The HTTP header was not correctly formatted diff --git a/include/libtorrent/session_handle.hpp b/include/libtorrent/session_handle.hpp index e90d4c8b462..2dafaf5db65 100644 --- a/include/libtorrent/session_handle.hpp +++ b/include/libtorrent/session_handle.hpp @@ -264,6 +264,12 @@ namespace libtorrent { // immediately, without waiting for the torrent to add. Notification of // the torrent being added is sent as add_torrent_alert. // + // The ``save_path`` field in add_torrent_params must be set to a valid + // path where the files for the torrent will be saved. Even when using a + // custom storage, this needs to be set to something. If the save_path + // is empty, the call to add_torrent() will throw a system_error + // exception. + // // The overload that does not take an error_code throws an exception on // error and is not available when building without exception support. // The torrent_handle returned by add_torrent() can be used to retrieve diff --git a/src/error_code.cpp b/src/error_code.cpp index 4775eee5d56..98c49ede4d1 100644 --- a/src/error_code.cpp +++ b/src/error_code.cpp @@ -206,7 +206,7 @@ namespace libtorrent { "invalid piece index in slot list", "pieces needs to be reordered", "fastresume not modified since last save", - "", + "invalid save_path", "", "", "", diff --git a/src/session_handle.cpp b/src/session_handle.cpp index e4bb290eeb8..0467a9b782e 100644 --- a/src/session_handle.cpp +++ b/src/session_handle.cpp @@ -405,7 +405,12 @@ namespace { #ifndef BOOST_NO_EXCEPTIONS torrent_handle session_handle::add_torrent(add_torrent_params&& params) { +#ifndef BOOST_NO_EXCEPTIONS + if (params.save_path.empty()) + aux::throw_ex(error_code(errors::invalid_save_path)); +#else TORRENT_ASSERT_PRECOND(!params.save_path.empty()); +#endif #if TORRENT_ABI_VERSION < 3 if (!params.info_hashes.has_v1() && !params.info_hashes.has_v2() && !params.ti) @@ -435,7 +440,11 @@ namespace { torrent_handle session_handle::add_torrent(add_torrent_params&& params, error_code& ec) { - TORRENT_ASSERT_PRECOND(!params.save_path.empty()); + if (params.save_path.empty()) + { + ec = error_code(errors::invalid_save_path); + return {}; + } #if TORRENT_ABI_VERSION < 3 if (!params.info_hashes.has_v1() && !params.info_hashes.has_v2() && !params.ti) @@ -467,7 +476,12 @@ namespace { void session_handle::async_add_torrent(add_torrent_params&& params) { +#ifndef BOOST_NO_EXCEPTIONS + if (params.save_path.empty()) + aux::throw_ex(error_code(errors::invalid_save_path)); +#else TORRENT_ASSERT_PRECOND(!params.save_path.empty()); +#endif #if TORRENT_ABI_VERSION < 3 if (!params.info_hashes.has_v1() && !params.info_hashes.has_v2() && !params.ti) @@ -528,7 +542,12 @@ namespace { , bool const add_paused , client_data_t userdata) { +#ifndef BOOST_NO_EXCEPTIONS + if (save_path.empty()) + aux::throw_ex(error_code(errors::invalid_save_path)); +#else TORRENT_ASSERT_PRECOND(!save_path.empty()); +#endif add_torrent_params p; p.trackers.push_back(tracker_url); diff --git a/test/test_session.cpp b/test/test_session.cpp index f77b3ce3822..65c2703bc88 100644 --- a/test/test_session.cpp +++ b/test/test_session.cpp @@ -126,6 +126,23 @@ TORRENT_TEST(async_add_torrent_deprecated_magnet) } #endif +TORRENT_TEST(async_add_torrent_no_save_path) +{ + settings_pack p = settings(); + p.set_int(settings_pack::alert_mask, ~0); + lt::session ses(p); + + add_torrent_params atp; + atp.info_hashes.v1.assign("abababababababababab"); + atp.save_path = ""; + TEST_THROW(ses.add_torrent(atp)); + TEST_THROW(ses.async_add_torrent(atp)); + + lt::error_code ec; + ses.add_torrent(atp, ec); + TORRENT_ASSERT(ec == error_code(lt::errors::invalid_save_path)); +} + TORRENT_TEST(async_add_torrent_duplicate_error) { settings_pack p = settings();