From 7dad993c04031ff6317d5ea470ac354c35c4b769 Mon Sep 17 00:00:00 2001 From: iphydf Date: Sat, 28 Dec 2024 17:30:48 +0000 Subject: [PATCH] refactor: Make Tox_Options own the passed proxy host and savedata. This way, client code can immediately free their data and can pass temporaries to the options setters. --- toxcore/tox.h | 28 +++++++++++++++++++----- toxcore/tox_api.c | 55 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index 56b5e9ffbd..8c1a5fe172 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -565,8 +565,11 @@ struct Tox_Options { * This member is ignored (it can be NULL) if proxy_type is * TOX_PROXY_TYPE_NONE. * - * The data pointed at by this member is owned by the user, so must - * outlive the options object. + * The setter tries to copy the string, but if it fails, the value is not + * copied and this member is set to the user-provided pointer. In that + * case, the user must not free the string until the Tox_Options object is + * freed. Client code can check whether allocation succeeded by comparing + * the value of this member to the user-provided pointer. */ const char *proxy_host; @@ -621,10 +624,13 @@ struct Tox_Options { Tox_Savedata_Type savedata_type; /** - * The savedata. + * The savedata (either a Tox save or a secret key) to load from. * - * The data pointed at by this member is owned by the user, so must outlive - * the options object. + * The setter tries to copy the string, but if it fails, the value is not + * copied and this member is set to the user-provided pointer. In that + * case, the user must not free the string until the Tox_Options object is + * freed. Client code can check whether allocation succeeded by comparing + * the value of this member to the user-provided pointer. */ const uint8_t *savedata_data; @@ -686,6 +692,18 @@ struct Tox_Options { * Default: false. May become true in the future (0.3.0). */ bool experimental_disable_dns; + + /** + * @brief Owned pointer to the savedata data. + * @private + */ + uint8_t *owned_savedata_data_; + + /** + * @brief Owned pointer to the proxy host. + * @private + */ + char *owned_proxy_host_; }; bool tox_options_get_ipv6_enabled(const Tox_Options *options); diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c index b979e4e1e2..d867316317 100644 --- a/toxcore/tox_api.c +++ b/toxcore/tox_api.c @@ -3,7 +3,8 @@ */ #include "tox.h" -#include +#include // free, malloc +#include // memcpy, strlen #include "ccompat.h" #include "tox_private.h" @@ -166,7 +167,25 @@ const char *tox_options_get_proxy_host(const Tox_Options *options) } void tox_options_set_proxy_host(Tox_Options *options, const char *proxy_host) { - options->proxy_host = proxy_host; + if (options->owned_proxy_host_ != nullptr) { + free(options->owned_proxy_host_); + options->owned_proxy_host_ = nullptr; + } + if (proxy_host == nullptr) { + options->proxy_host = nullptr; + return; + } + + const size_t proxy_host_length = strlen(proxy_host) + 1; + char *owned_ptr = (char *)malloc(proxy_host_length); + if (owned_ptr != nullptr) { + memcpy(owned_ptr, proxy_host, proxy_host_length); + options->proxy_host = owned_ptr; + options->owned_proxy_host_ = owned_ptr; + } else { + options->proxy_host = proxy_host; + options->owned_proxy_host_ = nullptr; + } } uint16_t tox_options_get_proxy_port(const Tox_Options *options) { @@ -290,13 +309,36 @@ const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) void tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length) { - options->savedata_data = savedata_data; + if (options->owned_savedata_data_ != nullptr) { + free(options->owned_savedata_data_); + options->owned_savedata_data_ = nullptr; + } + if (savedata_data == nullptr) { + options->savedata_data = nullptr; + options->savedata_length = 0; + return; + } + + uint8_t *owned_ptr = (uint8_t *)malloc(length); + if (owned_ptr != nullptr) { + memcpy(owned_ptr, savedata_data, length); + options->savedata_data = owned_ptr; + options->owned_savedata_data_ = owned_ptr; + } else { + options->savedata_data = savedata_data; + options->owned_savedata_data_ = nullptr; + } options->savedata_length = length; } void tox_options_default(Tox_Options *options) { if (options != nullptr) { + // Free any owned data. + tox_options_set_proxy_host(options, nullptr); + tox_options_set_savedata_data(options, nullptr, 0); + + // Set the rest to default values. const Tox_Options default_options = {false}; *options = default_options; tox_options_set_ipv6_enabled(options, true); @@ -327,7 +369,12 @@ Tox_Options *tox_options_new(Tox_Err_Options_New *error) void tox_options_free(Tox_Options *options) { - free(options); + if (options != nullptr) { + // Free any owned data. + tox_options_set_proxy_host(options, nullptr); + tox_options_set_savedata_data(options, nullptr, 0); + free(options); + } } const char *tox_user_status_to_string(Tox_User_Status value)