mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-05 21:59:21 +00:00
Reject out-of-range RPC values instead of narrowing them silently.
Guards choke group max, set-port and info-hash length; parsing now uses std::from_chars.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include <torrent/download/resource_manager.h>
|
||||
@@ -232,6 +233,9 @@ apply_cg_max_set(const torrent::Object::list_type& args, bool is_up) {
|
||||
int64_t second_arg = 0;
|
||||
rpc::parse_whole_value(args.back().as_string().c_str(), &second_arg);
|
||||
|
||||
if (second_arg < -1 || second_arg > std::numeric_limits<uint32_t>::max())
|
||||
throw torrent::input_error("Max unchoked must be between -1 and 4294967295.");
|
||||
|
||||
if (is_up)
|
||||
cg_get_group(args.front())->up_queue()->set_max_unchoked(second_arg);
|
||||
else
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
#define RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/object_storage.h"
|
||||
|
||||
void initialize_commands();
|
||||
|
||||
inline uint16_t
|
||||
checked_port_value(int64_t value, const char* label) {
|
||||
if (value < 0 || value > std::numeric_limits<uint16_t>::max())
|
||||
throw torrent::input_error(std::string("Invalid ") + label + " port number.");
|
||||
|
||||
return static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
//
|
||||
// Aliases with CMD_* for the below
|
||||
//
|
||||
|
||||
+4
-12
@@ -54,14 +54,6 @@ set_listen_port_range(const std::string& arg) {
|
||||
torrent::runtime::client_config()->set_listen_port_range(port_first, port_last);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
checked_local_port_value(int64_t value, const char* label) {
|
||||
if (value < 0 || value > 65535)
|
||||
throw torrent::input_error(std::string("Invalid ") + label + " port number.");
|
||||
|
||||
return static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
get_encryption() {
|
||||
auto encryption_modes = torrent::runtime::network_config()->encryption_modes();
|
||||
@@ -325,7 +317,7 @@ initialize_command_network() {
|
||||
auto nw_config = torrent::runtime::network_config();
|
||||
|
||||
CMD_ANY ("network.listen.port", [](auto, auto) { return torrent::runtime::network_manager()->listen_port(); });
|
||||
CMD_ANY_VALUE_V ("network.listen.port.set", [](auto, auto& value) { return torrent::runtime::network_manager()->set_listen_port(value); });
|
||||
CMD_ANY_VALUE_V ("network.listen.port.set", [](auto, auto& value) { return torrent::runtime::network_manager()->set_listen_port(checked_port_value(value, "listen")); });
|
||||
CMD_ANY ("network.listen.port.random", [](auto, auto) { return torrent::runtime::client_config()->listen_port_random(); });
|
||||
CMD_ANY_VALUE_V ("network.listen.port.random.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_listen_port_random(value); });
|
||||
CMD_ANY ("network.listen.port.range", [](auto, auto) { return listen_port_range(); });
|
||||
@@ -394,11 +386,11 @@ initialize_command_network() {
|
||||
CMD_ANY_STRING_V("network.local_address.ipv6.set", [nw_config](auto, auto& str) { return nw_config->set_local_inet6_address(str); });
|
||||
|
||||
CMD_ANY ("network.local_port", [nw_config](auto, auto) { return nw_config->local_port_best_match(); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.set", [nw_config](auto, auto& value) { return nw_config->set_local_port(checked_local_port_value(value, "local")); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.set", [nw_config](auto, auto& value) { return nw_config->set_local_port(checked_port_value(value, "local")); });
|
||||
CMD_ANY ("network.local_port.ipv4", [nw_config](auto, auto) { return nw_config->local_inet_port(); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.ipv4.set", [nw_config](auto, auto& value) { return nw_config->set_local_inet_port(checked_local_port_value(value, "local ipv4")); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.ipv4.set", [nw_config](auto, auto& value) { return nw_config->set_local_inet_port(checked_port_value(value, "local ipv4")); });
|
||||
CMD_ANY ("network.local_port.ipv6", [nw_config](auto, auto) { return nw_config->local_inet6_port(); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.ipv6.set", [nw_config](auto, auto& value) { return nw_config->set_local_inet6_port(checked_local_port_value(value, "local ipv6")); });
|
||||
CMD_ANY_VALUE_V ("network.local_port.ipv6.set", [nw_config](auto, auto& value) { return nw_config->set_local_inet6_port(checked_port_value(value, "local ipv6")); });
|
||||
|
||||
CMD_ANY ("network.proxy.global", [](auto, auto) { return torrent::runtime::proxy_manager()->proxy_url(); });
|
||||
CMD_ANY_STRING_V("network.proxy.global.set", [](auto, auto& str) { return torrent::runtime::proxy_manager()->set_proxy_url(str); });
|
||||
|
||||
@@ -142,7 +142,7 @@ initialize_command_tracker() {
|
||||
lt_log_print(torrent::LOG_DHT_ERROR, "dht.port.set is no longer supported, use dht.override_port.set", 0);
|
||||
});
|
||||
CMD2_ANY ("dht.override_port", [](auto, auto) { return torrent::runtime::network_config()->override_dht_port(); });
|
||||
CMD2_ANY_VALUE_V ("dht.override_port.set", [](auto, auto& value) { return torrent::runtime::network_manager()->set_dht_port(value); });
|
||||
CMD2_ANY_VALUE_V ("dht.override_port.set", [](auto, auto& value) { return torrent::runtime::network_manager()->set_dht_port(checked_port_value(value, "DHT override")); });
|
||||
|
||||
CMD2_ANY_STRING ("dht.add_node", [](auto, auto& str) { return apply_dht_add_node(str); });
|
||||
CMD2_ANY ("dht.statistics", [](auto, auto) { return control->dht_manager()->dht_statistics(); });
|
||||
|
||||
@@ -82,7 +82,7 @@ DownloadList::find(const torrent::HashString& hash) {
|
||||
|
||||
DownloadList::iterator
|
||||
DownloadList::find_hex(const char* hash) {
|
||||
if (strlen(hash) < 40)
|
||||
if (strlen(hash) != 40)
|
||||
return end();
|
||||
|
||||
torrent::HashString key;
|
||||
|
||||
+24
-3
@@ -1,5 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
@@ -113,10 +115,27 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
||||
if (unit <= 0)
|
||||
throw torrent::input_error("Command::string_to_value_unit(...) received unit <= 0.");
|
||||
|
||||
char* last;
|
||||
*value = strtoll(src, &last, base);
|
||||
const char* first = src;
|
||||
|
||||
while (std::isspace(static_cast<unsigned char>(*first)))
|
||||
first++;
|
||||
|
||||
if ((base == 0 || base == 16) && first[0] == '0' && (first[1] == 'x' || first[1] == 'X')) {
|
||||
first += 2;
|
||||
base = 16;
|
||||
|
||||
} else if (base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
const auto result = std::from_chars(first, first + std::strlen(first), *value, base);
|
||||
|
||||
if (result.ec == std::errc::result_out_of_range)
|
||||
return src;
|
||||
|
||||
if (result.ec != std::errc()) {
|
||||
*value = 0;
|
||||
|
||||
if (last == src) {
|
||||
if (strcasecmp(src, "no") == 0) { *value = 0; return src + strlen("no"); }
|
||||
if (strcasecmp(src, "yes") == 0) { *value = 1; return src + strlen("yes"); }
|
||||
if (strcasecmp(src, "true") == 0) { *value = 1; return src + strlen("true"); }
|
||||
@@ -125,6 +144,8 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) {
|
||||
return src;
|
||||
}
|
||||
|
||||
const char* last = result.ptr;
|
||||
|
||||
switch (*last) {
|
||||
case 'b':
|
||||
case 'B': ++last; break;
|
||||
|
||||
Reference in New Issue
Block a user