diff --git a/auto_tests/tox_one_test.c b/auto_tests/tox_one_test.c index 871aa443..350fafe9 100644 --- a/auto_tests/tox_one_test.c +++ b/auto_tests/tox_one_test.c @@ -30,12 +30,6 @@ START_TEST(test_one) Tox *tox1 = tox_new_log(0, 0, &index[0]); Tox *tox2 = tox_new_log(0, 0, &index[1]); - { - TOX_ERR_GET_PORT error; - ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); - ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error"); - } - uint8_t address[TOX_ADDRESS_SIZE]; tox_self_get_address(tox1, address); TOX_ERR_FRIEND_ADD error; @@ -115,6 +109,12 @@ START_TEST(test_one) tox_self_get_public_key(tox2, pk); ck_assert_msg(memcmp(pk, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key."); + { + TOX_ERR_GET_PORT error; + ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n"); + ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error"); + } + tox_kill(tox1); tox_kill(tox2); } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 77a19f30..d4c4526e 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2633,6 +2633,7 @@ void do_messenger(Messenger *m, void *userdata) #define SAVED_FRIEND_REQUEST_SIZE 1024 #define NUM_SAVED_PATH_NODES 8 + struct SAVED_FRIEND { uint8_t status; uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; @@ -2647,20 +2648,82 @@ struct SAVED_FRIEND { uint64_t last_seen_time; }; +static uint32_t friend_size() +{ + uint32_t data = 0; + const struct SAVED_FRIEND temp = { 0 }; + +#define VALUE_MEMBER(NAME) data += sizeof(temp.NAME) +#define ARRAY_MEMBER(NAME) data += sizeof(temp.NAME) + + // Exactly the same in friend_load, friend_save, and friend_size + VALUE_MEMBER(status); + ARRAY_MEMBER(real_pk); + ARRAY_MEMBER(info); + data++; // padding + VALUE_MEMBER(info_size); + ARRAY_MEMBER(name); + data++; // padding + VALUE_MEMBER(name_length); + ARRAY_MEMBER(statusmessage); + VALUE_MEMBER(statusmessage_length); + VALUE_MEMBER(userstatus); + data += 3; // padding + VALUE_MEMBER(friendrequest_nospam); + VALUE_MEMBER(last_seen_time); + +#undef VALUE_MEMBER +#undef ARRAY_MEMBER + + return data; +} + static uint32_t saved_friendslist_size(const Messenger *m) { - return count_friendlist(m) * sizeof(struct SAVED_FRIEND); + return count_friendlist(m) * friend_size(); +} + +static uint8_t *friend_save(const struct SAVED_FRIEND *temp, uint8_t *data) +{ +#define VALUE_MEMBER(NAME) \ + memcpy(data, &temp->NAME, sizeof(temp->NAME)); \ + data += sizeof(temp->NAME) + +#define ARRAY_MEMBER(NAME) \ + memcpy(data, temp->NAME, sizeof(temp->NAME)); \ + data += sizeof(temp->NAME) + + // Exactly the same in friend_load, friend_save, and friend_size + VALUE_MEMBER(status); + ARRAY_MEMBER(real_pk); + ARRAY_MEMBER(info); + data++; // padding + VALUE_MEMBER(info_size); + ARRAY_MEMBER(name); + data++; // padding + VALUE_MEMBER(name_length); + ARRAY_MEMBER(statusmessage); + VALUE_MEMBER(statusmessage_length); + VALUE_MEMBER(userstatus); + data += 3; // padding + VALUE_MEMBER(friendrequest_nospam); + VALUE_MEMBER(last_seen_time); + +#undef VALUE_MEMBER +#undef ARRAY_MEMBER + + return data; } static uint32_t friends_list_save(const Messenger *m, uint8_t *data) { uint32_t i; uint32_t num = 0; + uint8_t *cur_data = data; for (i = 0; i < m->numfriends; i++) { if (m->friendlist[i].status > 0) { - struct SAVED_FRIEND temp; - memset(&temp, 0, sizeof(struct SAVED_FRIEND)); + struct SAVED_FRIEND temp = { 0 }; temp.status = m->friendlist[i].status; memcpy(temp.real_pk, m->friendlist[i].real_pk, crypto_box_PUBLICKEYBYTES); @@ -2686,26 +2749,72 @@ static uint32_t friends_list_save(const Messenger *m, uint8_t *data) memcpy(&temp.last_seen_time, last_seen_time, sizeof(uint64_t)); } - memcpy(data + num * sizeof(struct SAVED_FRIEND), &temp, sizeof(struct SAVED_FRIEND)); + uint8_t *next_data = friend_save(&temp, cur_data); +#ifdef TOX_DEBUG + assert(next_data - cur_data == friend_size()); + assert(memcmp(cur_data, &temp, friend_size()) == 0); +#endif + cur_data = next_data; num++; } } - return num * sizeof(struct SAVED_FRIEND); +#ifdef TOX_DEBUG + assert(cur_data - data == num * friend_size()); +#endif + return cur_data - data; +} + +static const uint8_t *friend_load(struct SAVED_FRIEND *temp, const uint8_t *data) +{ +#define VALUE_MEMBER(NAME) \ + memcpy(&temp->NAME, data, sizeof(temp->NAME)); \ + data += sizeof(temp->NAME) + +#define ARRAY_MEMBER(NAME) \ + memcpy(temp->NAME, data, sizeof(temp->NAME)); \ + data += sizeof(temp->NAME) + + // Exactly the same in friend_load, friend_save, and friend_size + VALUE_MEMBER(status); + ARRAY_MEMBER(real_pk); + ARRAY_MEMBER(info); + data++; // padding + VALUE_MEMBER(info_size); + ARRAY_MEMBER(name); + data++; // padding + VALUE_MEMBER(name_length); + ARRAY_MEMBER(statusmessage); + VALUE_MEMBER(statusmessage_length); + VALUE_MEMBER(userstatus); + data += 3; // padding + VALUE_MEMBER(friendrequest_nospam); + VALUE_MEMBER(last_seen_time); + +#undef VALUE_MEMBER +#undef ARRAY_MEMBER + + return data; } static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length) { - if (length % sizeof(struct SAVED_FRIEND) != 0) { + if (length % friend_size() != 0) { return -1; } - uint32_t num = length / sizeof(struct SAVED_FRIEND); + uint32_t num = length / friend_size(); uint32_t i; + const uint8_t *cur_data = data; for (i = 0; i < num; ++i) { - struct SAVED_FRIEND temp; - memcpy(&temp, data + i * sizeof(struct SAVED_FRIEND), sizeof(struct SAVED_FRIEND)); + struct SAVED_FRIEND temp = { 0 }; + const uint8_t *next_data = friend_load(&temp, cur_data); +#ifdef TOX_DEBUG + assert(next_data - cur_data == friend_size()); + assert(memcmp(&temp, cur_data, friend_size()) == 0); +#endif + cur_data = next_data; if (temp.status >= 3) { int fnum = m_addfriend_norequest(m, temp.real_pk);