diff --git a/auto_tests/auto_test_support.c b/auto_tests/auto_test_support.c index 483e3130b7..3aed474a53 100644 --- a/auto_tests/auto_test_support.c +++ b/auto_tests/auto_test_support.c @@ -3,11 +3,10 @@ #include "check_compat.h" #include "../testing/misc_tools.h" -#include "../toxcore/Messenger.h" #include "../toxcore/mono_time.h" #include "../toxcore/tox_dispatch.h" #include "../toxcore/tox_events.h" -#include "../toxcore/tox_struct.h" +#include "../toxcore/tox_struct.h" // IWYU pragma: keep #include "auto_test_support.h" @@ -211,7 +210,7 @@ void reload(AutoTox *autotox) ck_assert(options != nullptr); tox_options_set_ipv6_enabled(options, USE_IPV6); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size); + ck_assert(tox_options_set_savedata(options, autotox->save_state, autotox->save_size)); autotox->tox = tox_new_log(options, nullptr, &autotox->index); ck_assert(autotox->tox != nullptr); autotox->dispatch = tox_dispatch_new(nullptr); diff --git a/auto_tests/conference_test.c b/auto_tests/conference_test.c index af1cd288f8..eddb20d7d9 100644 --- a/auto_tests/conference_test.c +++ b/auto_tests/conference_test.c @@ -248,7 +248,7 @@ static void run_conference_tests(AutoTox *autotoxes) struct Tox_Options *const options = tox_options_new(nullptr); ck_assert(options != nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, save[i], save_size[i]); + ck_assert(tox_options_set_savedata(options, save[i], save_size[i])); autotoxes[i].tox = tox_new_log(options, nullptr, &autotoxes[i].index); ck_assert(autotoxes[i].tox != nullptr); tox_options_free(options); diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 3573337e49..ecb1f233de 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -3,7 +3,6 @@ #include #include -#include "../testing/misc_tools.h" #include "../toxcore/ccompat.h" #include "../toxcore/crypto_core.h" #include "../toxcore/tox.h" @@ -54,7 +53,7 @@ static void test_save_friend(void) struct Tox_Options *options = tox_options_new(nullptr); ck_assert(options != nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, enc_data, size2); + ck_assert(tox_options_set_savedata(options, enc_data, size2)); Tox_Err_New err2; Tox *tox3 = tox_new_log(options, &err2, nullptr); @@ -66,7 +65,7 @@ static void test_save_friend(void) Tox_Err_Decryption err3; ret = tox_pass_decrypt(enc_data, size2, (const uint8_t *)"correcthorsebatterystaple", 25, dec_data, &err3); ck_assert_msg(ret, "failed to decrypt save: %d", err3); - tox_options_set_savedata_data(options, dec_data, size); + ck_assert(tox_options_set_savedata(options, dec_data, size)); tox3 = tox_new_log(options, &err2, nullptr); ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %d", err2); uint8_t address2[TOX_PUBLIC_KEY_SIZE]; @@ -102,7 +101,7 @@ static void test_save_friend(void) // and now with the code in use (I only bothered with manually to debug this, and it seems a waste // to remove the manual check now that it's there) - tox_options_set_savedata_data(options, out1, size); + ck_assert(tox_options_set_savedata(options, out1, size)); Tox *tox4 = tox_new_log(options, &err2, nullptr); ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third"); uint8_t address5[TOX_PUBLIC_KEY_SIZE]; diff --git a/auto_tests/file_saving_test.c b/auto_tests/file_saving_test.c index e90aeff4d7..76f20b23a4 100644 --- a/auto_tests/file_saving_test.c +++ b/auto_tests/file_saving_test.c @@ -91,9 +91,8 @@ static void load_data_decrypted(void) struct Tox_Options *options = tox_options_new(nullptr); ck_assert(options != nullptr); - tox_options_set_experimental_owned_data(options, true); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - ck_assert(tox_options_set_savedata_data(options, clear, clear_size)); + ck_assert(tox_options_set_savedata(options, clear, clear_size)); free(clear); Tox_Err_New err; diff --git a/auto_tests/group_save_test.c b/auto_tests/group_save_test.c index 26b41d078f..63fe5af30e 100644 --- a/auto_tests/group_save_test.c +++ b/auto_tests/group_save_test.c @@ -246,7 +246,7 @@ static void group_save_test(AutoTox *autotoxes) ck_assert(options != nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, save, save_length); + ck_assert(tox_options_set_savedata(options, save, save_length)); tox_options_set_experimental_groups_persistence(options, true); Tox *new_tox = tox_new_log(options, nullptr, nullptr); diff --git a/auto_tests/save_compatibility_test.c b/auto_tests/save_compatibility_test.c index 6267f669b1..d5ea80f375 100644 --- a/auto_tests/save_compatibility_test.c +++ b/auto_tests/save_compatibility_test.c @@ -79,7 +79,7 @@ static void test_save_compatibility(const char *save_path) ck_assert_msg(save_data != nullptr, "error while reading save file '%s'", save_path); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, save_data, size); + ck_assert(tox_options_set_savedata(options, save_data, size)); size_t index = 0; Tox_Err_New err; diff --git a/auto_tests/save_friend_test.c b/auto_tests/save_friend_test.c index 339690f2b8..66f31a8110 100644 --- a/auto_tests/save_friend_test.c +++ b/auto_tests/save_friend_test.c @@ -149,11 +149,12 @@ int main(void) size_t save_size = tox_get_savedata_size(tox1); uint8_t *savedata = (uint8_t *)malloc(save_size); + ck_assert(savedata != nullptr); tox_get_savedata(tox1, savedata); struct Tox_Options *const options = tox_options_new(nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, savedata, save_size); + ck_assert(tox_options_set_savedata(options, savedata, save_size)); Tox *const tox_to_compare = tox_new_log(options, nullptr, nullptr); diff --git a/auto_tests/save_load_test.c b/auto_tests/save_load_test.c index f4158856de..e355c9a80a 100644 --- a/auto_tests/save_load_test.c +++ b/auto_tests/save_load_test.c @@ -9,8 +9,7 @@ #include "../testing/misc_tools.h" #include "../toxcore/ccompat.h" #include "../toxcore/tox.h" -#include "../toxcore/tox_struct.h" -#include "../toxcore/util.h" +#include "../toxcore/tox_struct.h" // IWYU pragma: keep #include "auto_test_support.h" #include "check_compat.h" @@ -88,7 +87,7 @@ static void reload_tox(Tox **tox, struct Tox_Options *const in_opts, void *user_ tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, buffer + extra, save_size1); + ck_assert(tox_options_set_savedata(options, buffer + extra, save_size1)); *tox = tox_new_log(options, nullptr, user_data); diff --git a/other/fun/create_savedata.c b/other/fun/create_savedata.c index 8456940239..55f27c6b0f 100644 --- a/other/fun/create_savedata.c +++ b/other/fun/create_savedata.c @@ -17,7 +17,7 @@ #include "../../toxcore/tox.h" #include "create_common.h" -static bool create_tox(const unsigned char *const secret_key, Tox **const tox) +static bool create_tox(const uint8_t secret_key[TOX_SECRET_KEY_SIZE], Tox **const tox) { Tox_Err_Options_New options_error; struct Tox_Options *const options = tox_options_new(&options_error); @@ -28,7 +28,10 @@ static bool create_tox(const unsigned char *const secret_key, Tox **const tox) } tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY); - tox_options_set_savedata_data(options, secret_key, crypto_box_SECRETKEYBYTES); + if (!tox_options_set_savedata(options, secret_key, TOX_SECRET_KEY_SIZE)) { + tox_options_free(options); + return false; + } Tox_Err_New tox_error; *tox = tox_new(options, &tox_error); diff --git a/testing/fuzzing/toxsave_fuzz_test.cc b/testing/fuzzing/toxsave_fuzz_test.cc index f48c2bf013..eba081dc1c 100644 --- a/testing/fuzzing/toxsave_fuzz_test.cc +++ b/testing/fuzzing/toxsave_fuzz_test.cc @@ -21,7 +21,10 @@ void TestSaveDataLoading(Fuzz_Data &input) CONSUME_OR_RETURN(const uint8_t *savedata, input, savedata_size); // pass test data to Tox - tox_options_set_savedata_data(tox_options, savedata, savedata_size); + if (!tox_options_set_savedata(tox_options, savedata, savedata_size)) { + tox_options_free(tox_options); + return; + } tox_options_set_savedata_type(tox_options, TOX_SAVEDATA_TYPE_TOX_SAVE); Tox_Options_Testing tox_options_testing; diff --git a/toxcore/tox_options.c b/toxcore/tox_options.c index d67a8aebd0..789a727d03 100644 --- a/toxcore/tox_options.c +++ b/toxcore/tox_options.c @@ -123,14 +123,6 @@ void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type saved { options->savedata_type = savedata_type; } -size_t tox_options_get_savedata_length(const Tox_Options *options) -{ - return options->savedata_length; -} -void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length) -{ - options->savedata_length = savedata_length; -} tox_log_cb *tox_options_get_log_callback(const Tox_Options *options) { return options->log_callback; @@ -199,50 +191,82 @@ void tox_options_set_experimental_owned_data( options->experimental_owned_data = experimental_owned_data; } -const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) +void tox_options_get_savedata(const Tox_Options *options, uint8_t *savedata) { - return options->savedata_data; + memcpy(savedata, options->savedata_data, options->savedata_length); } -bool tox_options_set_savedata_data(Tox_Options *options, const uint8_t *savedata_data, size_t length) +size_t tox_options_get_savedata_size(const Tox_Options *options) { - if (!options->experimental_owned_data) { - options->savedata_data = savedata_data; - options->savedata_length = length; - return true; - } + return options->savedata_length; +} +bool tox_options_set_savedata(Tox_Options *options, const uint8_t *savedata, size_t savedata_size) +{ if (options->owned_savedata_data != nullptr) { free(options->owned_savedata_data); + options->savedata_data = nullptr; + options->savedata_length = 0; options->owned_savedata_data = nullptr; } - if (savedata_data == nullptr) { + + if (savedata == nullptr) { options->savedata_data = nullptr; options->savedata_length = 0; + options->owned_savedata_data = nullptr; return true; } - uint8_t *owned_ptr = (uint8_t *)malloc(length); + uint8_t *owned_ptr = (uint8_t *)malloc(savedata_size); if (owned_ptr == nullptr) { + return false; + } + + memcpy(owned_ptr, savedata, savedata_size); + options->savedata_data = owned_ptr; + options->savedata_length = savedata_size; + options->owned_savedata_data = owned_ptr; + return true; +} + +// Deprecated functions. +bool tox_options_set_savedata_data( + Tox_Options *options, const uint8_t savedata_data[], size_t length) +{ + if (!options->experimental_owned_data) { + options->savedata_data = savedata_data; + options->savedata_length = length; + return true; + } + + if (!tox_options_set_savedata(options, savedata_data, length)) { options->savedata_data = savedata_data; options->savedata_length = length; options->owned_savedata_data = nullptr; return false; } - memcpy(owned_ptr, savedata_data, length); - options->savedata_data = owned_ptr; - options->savedata_length = length; - options->owned_savedata_data = owned_ptr; return true; } +void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length) +{ + options->savedata_length = savedata_length; +} +const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) +{ + return options->savedata_data; +} +size_t tox_options_get_savedata_length(const Tox_Options *options) +{ + return tox_options_get_savedata_size(options); +} 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); + tox_options_set_savedata(options, nullptr, 0); // Set the rest to default values. const Tox_Options default_options = {false}; @@ -279,7 +303,7 @@ void tox_options_free(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); + tox_options_set_savedata(options, nullptr, 0); free(options); } } diff --git a/toxcore/tox_options.h b/toxcore/tox_options.h index 7d8b7aafaa..f2b2a4d168 100644 --- a/toxcore/tox_options.h +++ b/toxcore/tox_options.h @@ -74,8 +74,8 @@ const char *tox_savedata_type_to_string(Tox_Savedata_Type value); * least extend between registering and unregistering it or tox_kill. * * Other toxcore modules such as toxav may concurrently call this callback at - * any time. Thus, user code must make sure it is equipped to handle concurrent - * execution, e.g. by employing appropriate mutex locking. + * any time. Thus, user code must make sure it is equipped to handle + * concurrent execution, e.g. by employing appropriate mutex locking. * * When using the experimental_thread_safety option, no Tox API functions can * be called from within the log callback. @@ -87,9 +87,9 @@ const char *tox_savedata_type_to_string(Tox_Savedata_Type value); * @param message The log message. * @param user_data The user data pointer passed to tox_new in options. */ -typedef void tox_log_cb(struct Tox *tox, Tox_Log_Level level, const char *file, - uint32_t line, const char *func, const char *message, - void *user_data); +typedef void tox_log_cb(struct Tox *tox, Tox_Log_Level level, + const char *file, uint32_t line, const char *func, + const char *message, void *user_data); /** * @brief This struct contains all the startup options for Tox. @@ -123,19 +123,20 @@ struct Tox_Options { /** * Enable the use of UDP communication when available. * - * Setting this to false will force Tox to use TCP only. Communications will - * need to be relayed through a TCP relay node, potentially slowing them - * down. + * Setting this to false will force Tox to use TCP only. Communications + * will need to be relayed through a TCP relay node, potentially slowing + * them down. * - * If a proxy is enabled, UDP will be disabled if either the Tox library or - * the proxy don't support proxying UDP messages. + * If a proxy is enabled, UDP will be disabled if either the Tox library + * or the proxy don't support proxying UDP messages. */ bool udp_enabled; /** * Enable local network peer discovery. * - * Disabling this will cause Tox to not look for peers on the local network. + * Disabling this will cause Tox to not look for peers on the local + * network. */ bool local_discovery_enabled; @@ -154,9 +155,10 @@ struct Tox_Options { /** * The IP address or DNS name of the proxy to be used. * - * If used, this must be non-NULL and be a valid DNS name. The name must not - * exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a NUL-terminated C - * string format (TOX_MAX_HOSTNAME_LENGTH includes the NUL byte). + * If used, this must be non-NULL and be a valid DNS name. The name must + * not exceed TOX_MAX_HOSTNAME_LENGTH characters, and be in a + * NUL-terminated C string format (TOX_MAX_HOSTNAME_LENGTH includes the + * NUL byte). * * This member is ignored (it can be NULL) if proxy_type is * TOX_PROXY_TYPE_NONE. @@ -241,9 +243,9 @@ struct Tox_Options { /** * These options are experimental, so avoid writing code that depends on - * them. Options marked "experimental" may change their behaviour or go away - * entirely in the future, or may be renamed to something non-experimental - * if they become part of the supported API. + * them. Options marked "experimental" may change their behaviour or go + * away entirely in the future, or may be renamed to something + * non-experimental if they become part of the supported API. */ /** * Make public API functions thread-safe using a per-instance lock. @@ -254,8 +256,8 @@ struct Tox_Options { /** * Enable saving DHT-based group chats to Tox save data (via - * `tox_get_savedata`). This format will change in the future, so don't rely - * on it. + * `tox_get_savedata`). This format will change in the future, so don't + * rely on it. * * As an alternative, clients can save the group chat ID in client-owned * savedata. Then, when the client starts, it can use `tox_group_join` @@ -286,11 +288,11 @@ struct Tox_Options { /** * @brief Whether the savedata data is owned by the Tox_Options object. * - * If true, the setters for savedata and proxy_host try to copy the string. - * If that fails, the value is not copied and the 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 checking the returned bool. If + * If true, the setters for savedata and proxy_host try to copy the + * string. If that fails, the value is not copied and the 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 checking the returned bool. If * experimental_owned_data is false, it will always return true. If set to * true, the return value will be false on allocation failure. * @@ -362,14 +364,49 @@ Tox_Savedata_Type tox_options_get_savedata_type(const Tox_Options *options); void tox_options_set_savedata_type(Tox_Options *options, Tox_Savedata_Type savedata_type); +// TODO(iphydf): Uncomment after migration. +// #ifndef TOX_HIDE_DEPRECATED +/** + * @deprecated Use tox_options_get_savedata instead. + */ const uint8_t *tox_options_get_savedata_data(const Tox_Options *options); +/** + * @deprecated Use tox_options_get_savedata_size instead. + */ +size_t tox_options_get_savedata_length(const Tox_Options *options); + +/** + * @brief Set the savedata data and length. + * + * If experimental_owned_data is false, the savedata_data pointer must remain + * valid until the Tox_Options object is freed. If experimental_owned_data is + * true, the savedata_data pointer is copied and the user is free to free the + * original pointer, but ONLY IF the function returns true. If the function + * returns false, the savedata_data pointer is not copied and the user must not + * free the original pointer until the Tox_Options object is freed. + * + * @deprecated Use tox_options_set_savedata instead. + */ bool tox_options_set_savedata_data( Tox_Options *options, const uint8_t savedata_data[], size_t length); -size_t tox_options_get_savedata_length(const Tox_Options *options); - +/** + * @deprecated Use tox_options_set_savedata instead. + */ void tox_options_set_savedata_length(Tox_Options *options, size_t savedata_length); +// #endif /* TOX_HIDE_DEPRECATED */ + +void tox_options_get_savedata(const Tox_Options *options, uint8_t savedata[]); + +size_t tox_options_get_savedata_size(const Tox_Options *options); + +/** @brief Set the savedata data and length. + * + * Copies the savedata data and length into the options object. On allocation + * failure, returns false and does not set the savedata data and length. + */ +bool tox_options_set_savedata(Tox_Options *options, const uint8_t savedata[], size_t savedata_size); tox_log_cb *tox_options_get_log_callback(const Tox_Options *options); @@ -425,14 +462,15 @@ typedef enum Tox_Err_Options_New { const char *tox_err_options_new_to_string(Tox_Err_Options_New value); /** - * @brief Allocates a new Tox_Options object and initialises it with the default - * options. + * @brief Allocates a new Tox_Options object and initialises it with the + * default options. * * This function can be used to preserve long term ABI compatibility by - * giving the responsibility of allocation and deallocation to the Tox library. + * giving the responsibility of allocation and deallocation to the Tox + * library. * - * Objects returned from this function must be freed using the tox_options_free - * function. + * Objects returned from this function must be freed using the + * tox_options_free function. * * @return A new Tox_Options object with default options or NULL on failure. */ diff --git a/toxcore/tox_test.cc b/toxcore/tox_test.cc index 23a53b0c0d..194230a592 100644 --- a/toxcore/tox_test.cc +++ b/toxcore/tox_test.cc @@ -161,7 +161,7 @@ TEST(Tox, OneTest) Tox_Err_New err_n; tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, data.data(), data.size()); + ASSERT_TRUE(tox_options_set_savedata(options, data.data(), data.size())); tox2 = tox_new(options, &err_n); EXPECT_EQ(err_n, TOX_ERR_NEW_OK) << "Load failed"; @@ -190,7 +190,7 @@ TEST(Tox, OneTest) tox_options_default(options); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY); - tox_options_set_savedata_data(options, sk.data(), sk.size()); + ASSERT_TRUE(tox_options_set_savedata(options, sk.data(), sk.size())); tox2 = tox_new(options, &err_n); ASSERT_EQ(err_n, TOX_ERR_NEW_OK) << "Load failed"; tox_self_set_nospam(tox2, tox_self_get_nospam(tox1));