From 0aaa4700537f180d4afba4260b0efc75eafef36f Mon Sep 17 00:00:00 2001 From: sirus20x6 Date: Fri, 13 Mar 2026 20:28:38 -0500 Subject: [PATCH] Fix resource leaks and minor issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Close pipe fds on fork failure in ExecFile::execute - Add exception-safe fclose in cmd_file_append via try/catch - Add overflow guards before K/M/G bit shifts in parse_whole_value - Fix %u format for int* in sscanf (change to %d) - Fix typo "atter"→"after" in error message --- src/command_local.cc | 10 +++++++--- src/core/download.cc | 2 +- src/option_parser.cc | 2 +- src/rpc/exec_file.cc | 7 ++++++- src/rpc/parse.cc | 12 +++++++++--- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/command_local.cc b/src/command_local.cc index 3374ae69..d624ecae 100644 --- a/src/command_local.cc +++ b/src/command_local.cc @@ -173,9 +173,13 @@ cmd_file_append(const torrent::Object::list_type& args) { if (output == nullptr) throw torrent::input_error("Could not append to file '" + args.front().as_string() + "': " + std::strerror(errno)); - file_print_list(++args.begin(), args.end(), output, file_print_delim_space); - - fprintf(output, "\n"); + try { + file_print_list(++args.begin(), args.end(), output, file_print_delim_space); + fprintf(output, "\n"); + } catch (...) { + fclose(output); + throw; + } fclose(output); return torrent::Object(); } diff --git a/src/core/download.cc b/src/core/download.cc index 03da3c21..08cd5d28 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -137,7 +137,7 @@ Download::set_root_directory(const std::string& path) { rpc::call_command("d.state.set", (int64_t)0, rpc::make_target(this)); control->core()->download_list()->close_directly(this); - throw torrent::input_error("Cannot change the directory of an open download atter the files have been moved."); + throw torrent::input_error("Cannot change the directory of an open download after the files have been moved."); } control->core()->download_list()->close_directly(this); diff --git a/src/option_parser.cc b/src/option_parser.cc index 2c640e97..49fe422e 100644 --- a/src/option_parser.cc +++ b/src/option_parser.cc @@ -137,7 +137,7 @@ void OptionParser::call_int_pair(slot_int_pair slot, const std::string& arg) { int a, b; - if (std::sscanf(arg.c_str(), "%u-%u", &a, &b) != 2) + if (std::sscanf(arg.c_str(), "%d-%d", &a, &b) != 2) throw std::runtime_error("Invalid argument, \"" + arg + "\" should be \"a-b\""); slot(a, b); diff --git a/src/rpc/exec_file.cc b/src/rpc/exec_file.cc index 2faa33f1..010e295e 100644 --- a/src/rpc/exec_file.cc +++ b/src/rpc/exec_file.cc @@ -41,8 +41,13 @@ ExecFile::execute(const char* file, char* const* argv, int flags) { pid_t childPid = fork(); - if (childPid == -1) + if (childPid == -1) { + if (flags & flag_capture) { + ::close(pipeFd[0]); + ::close(pipeFd[1]); + } throw torrent::input_error("ExecFile::execute(...) Fork failed."); + } if (childPid == 0) { if (flags & flag_background) { diff --git a/src/rpc/parse.cc b/src/rpc/parse.cc index ced049bd..3953fa84 100644 --- a/src/rpc/parse.cc +++ b/src/rpc/parse.cc @@ -120,11 +120,17 @@ parse_value_nothrow(const char* src, int64_t* value, int base, int unit) { case 'b': case 'B': ++last; break; case 'k': - case 'K': *value = *value << 10; ++last; break; + case 'K': + if (*value > (int64_t)0x1FFFFFFFFFFFFF) return src; // overflow guard + *value = *value << 10; ++last; break; case 'm': - case 'M': *value = *value << 20; ++last; break; + case 'M': + if (*value > (int64_t)0x7FFFFFFFFFF) return src; // overflow guard + *value = *value << 20; ++last; break; case 'g': - case 'G': *value = *value << 30; ++last; break; + case 'G': + if (*value > (int64_t)0x1FFFFFFFF) return src; // overflow guard + *value = *value << 30; ++last; break; // case ' ': // case '\0': *value = *value * unit; break; // default: throw torrent::input_error("Could not parse value.");