Skip to content

Commit

Permalink
refactor: Add mem module to allow tests to override allocators.
Browse files Browse the repository at this point in the history
This will allow us to do more interesting things with memory allocation
within toxcore, and allow fuzzers to explore various allocation failure
paths.
  • Loading branch information
iphydf committed Aug 23, 2023
1 parent a1e2458 commit ac03d7d
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 44 deletions.
8 changes: 8 additions & 0 deletions toxcore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ cc_library(
visibility = ["//c-toxcore:__subpackages__"],
)

cc_library(
name = "mem",
srcs = ["mem.c"],
hdrs = ["mem.h"],
visibility = ["//c-toxcore:__subpackages__"],
)

cc_library(
name = "ccompat",
srcs = ["ccompat.c"],
Expand Down Expand Up @@ -766,6 +773,7 @@ cc_library(
":group",
":group_moderation",
":logger",
":mem",
":mono_time",
":network",
"//c-toxcore/toxencryptsave:defines",
Expand Down
61 changes: 61 additions & 0 deletions toxcore/mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2018 The TokTok team.
* Copyright © 2013 Tox project.
*/

#include "mem.h"

#include <stdlib.h>

static void *sys_malloc(void *obj, uint32_t size)
{
return malloc(size);
}

static void *sys_calloc(void *obj, uint32_t nmemb, uint32_t size)
{
return calloc(nmemb, size);
}

static void *sys_realloc(void *obj, void *ptr, uint32_t size)
{
return realloc(ptr, size);
}

static void sys_free(void *obj, void *ptr)
{
free(ptr);
}

static const Memory_Funcs system_memory_funcs = {
sys_malloc,
sys_calloc,
sys_realloc,
sys_free,
};
static const Memory system_memory_obj = {&system_memory_funcs};

const Memory *system_memory(void)
{
return &system_memory_obj;
}

void *mem_malloc(const Memory *mem, uint32_t size)
{
return mem->funcs->malloc(mem->obj, size);
}

void *mem_calloc(const Memory *mem, uint32_t nmemb, uint32_t size)
{
return mem->funcs->calloc(mem->obj, nmemb, size);
}

void *mem_realloc(const Memory *mem, void *ptr, uint32_t size)
{
return mem->funcs->realloc(mem->obj, ptr, size);
}

void mem_free(const Memory *mem, void *ptr)
{
mem->funcs->free(mem->obj, ptr);
}
47 changes: 47 additions & 0 deletions toxcore/mem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2018 The TokTok team.
* Copyright © 2013 Tox project.
*/

/**
* Datatypes, functions and includes for the core networking.
*/
#ifndef C_TOXCORE_TOXCORE_MEM_H
#define C_TOXCORE_TOXCORE_MEM_H

#include <stdint.h> // uint*_t

#ifdef __cplusplus
extern "C" {
#endif

typedef void *mem_malloc_cb(void *obj, uint32_t size);
typedef void *mem_calloc_cb(void *obj, uint32_t nmemb, uint32_t size);
typedef void *mem_realloc_cb(void *obj, void *ptr, uint32_t size);
typedef void mem_free_cb(void *obj, void *ptr);

/** @brief Functions wrapping standard C memory allocation functions. */
typedef struct Memory_Funcs {
mem_malloc_cb *malloc;
mem_calloc_cb *calloc;
mem_realloc_cb *realloc;
mem_free_cb *free;
} Memory_Funcs;

typedef struct Memory {
const Memory_Funcs *funcs;
void *obj;
} Memory;

const Memory *system_memory(void);

void *mem_malloc(const Memory *mem, uint32_t size);
void *mem_calloc(const Memory *mem, uint32_t nmemb, uint32_t size);
void *mem_realloc(const Memory *mem, void *ptr, uint32_t size);
void mem_free(const Memory *mem, void *ptr);

#ifdef __cplusplus
} // extern "C"
#endif

#endif
83 changes: 39 additions & 44 deletions toxcore/tox.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "group_chats.h"
#include "group_moderation.h"
#include "logger.h"
#include "mem.h"
#include "mono_time.h"
#include "network.h"
#include "tox_private.h"
Expand Down Expand Up @@ -626,18 +627,6 @@ static int tox_load(Tox *tox, const uint8_t *data, uint32_t length)

Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
{
Tox *tox = (Tox *)calloc(1, sizeof(Tox));

if (tox == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
return nullptr;
}

Messenger_Options m_options = {0};

bool load_savedata_sk = false;
bool load_savedata_tox = false;

struct Tox_Options *default_options = nullptr;

if (options == nullptr) {
Expand All @@ -651,7 +640,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)

case TOX_ERR_OPTIONS_NEW_MALLOC: {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
free(tox);
return nullptr;
}
}
Expand All @@ -660,11 +648,28 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
const struct Tox_Options *const opts = options != nullptr ? options : default_options;
assert(opts != nullptr);

const Tox_System *sys = tox_options_get_operating_system(opts);
const Tox_System default_system = tox_default_system();

if (sys == nullptr) {
sys = &default_system;
}

if (sys->rng == nullptr || sys->ns == nullptr || sys->mem == nullptr) {
// TODO(iphydf): Not quite right, but similar.
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
return nullptr;
}

Messenger_Options m_options = {0};

bool load_savedata_sk = false;
bool load_savedata_tox = false;

if (tox_options_get_savedata_type(opts) != TOX_SAVEDATA_TYPE_NONE) {
if (tox_options_get_savedata_data(opts) == nullptr || tox_options_get_savedata_length(opts) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
free(tox);
return nullptr;
}
}
Expand All @@ -673,7 +678,6 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
if (tox_options_get_savedata_length(opts) != TOX_SECRET_KEY_SIZE) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
free(tox);
return nullptr;
}

Expand All @@ -682,14 +686,12 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
if (tox_options_get_savedata_length(opts) < TOX_ENC_SAVE_MAGIC_LENGTH) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
tox_options_free(default_options);
free(tox);
return nullptr;
}

if (memcmp(tox_options_get_savedata_data(opts), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
tox_options_free(default_options);
free(tox);
return nullptr;
}

Expand All @@ -709,6 +711,13 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
m_options.local_discovery_enabled = false;
}

Tox *tox = (Tox *)mem_calloc(sys->mem, 1, sizeof(Tox));

if (tox == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
return nullptr;
}

tox->log_callback = tox_options_get_log_callback(opts);
m_options.log_callback = tox_log_handler;
m_options.log_context = tox;
Expand All @@ -733,34 +742,20 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
default: {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
tox_options_free(default_options);
free(tox);
mem_free(sys->mem, tox);
return nullptr;
}
}

const Tox_System *sys = tox_options_get_operating_system(opts);
const Tox_System default_system = tox_default_system();

if (sys == nullptr) {
sys = &default_system;
}

if (sys->rng == nullptr || sys->ns == nullptr) {
// TODO(iphydf): Not quite right, but similar.
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
tox_options_free(default_options);
free(tox);
return nullptr;
}

tox->rng = *sys->rng;
tox->ns = *sys->ns;
tox->mem = *sys->mem;

if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
if (tox_options_get_proxy_port(opts) == 0) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
tox_options_free(default_options);
free(tox);
mem_free(sys->mem, tox);
return nullptr;
}

Expand All @@ -777,7 +772,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
// TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
tox_options_free(default_options);
free(tox);
mem_free(sys->mem, tox);
return nullptr;
}

Expand All @@ -789,17 +784,17 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
if (tox->mono_time == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
tox_options_free(default_options);
free(tox);
mem_free(sys->mem, tox);
return nullptr;
}

if (tox_options_get_experimental_thread_safety(opts)) {
tox->mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
tox->mutex = (pthread_mutex_t *)mem_calloc(sys->mem, 1, sizeof(pthread_mutex_t));

if (tox->mutex == nullptr) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
tox_options_free(default_options);
free(tox);
mem_free(sys->mem, tox);
return nullptr;
}

Expand Down Expand Up @@ -835,8 +830,8 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
pthread_mutex_destroy(tox->mutex);
}

free(tox->mutex);
free(tox);
mem_free(sys->mem, tox->mutex);
mem_free(sys->mem, tox);
return nullptr;
}

Expand All @@ -851,8 +846,8 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error)
pthread_mutex_destroy(tox->mutex);
}

free(tox->mutex);
free(tox);
mem_free(sys->mem, tox->mutex);
mem_free(sys->mem, tox);

SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
return nullptr;
Expand Down Expand Up @@ -933,10 +928,10 @@ void tox_kill(Tox *tox)

if (tox->mutex != nullptr) {
pthread_mutex_destroy(tox->mutex);
free(tox->mutex);
mem_free(&tox->mem, tox->mutex);
}

free(tox);
mem_free(&tox->mem, tox);
}

static uint32_t end_size(void)
Expand Down
2 changes: 2 additions & 0 deletions toxcore/tox_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <assert.h>

#include "ccompat.h"
#include "mem.h"
#include "network.h"
#include "tox_struct.h"

Expand All @@ -28,6 +29,7 @@ Tox_System tox_default_system(void)
nullptr, // mono_time_user_data
system_random(),
system_network(),
system_memory(),
};
return sys;
}
Expand Down
1 change: 1 addition & 0 deletions toxcore/tox_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct Tox_System {
void *mono_time_user_data;
const struct Random *rng;
const struct Network *ns;
const struct Memory *mem;
};

Tox_System tox_default_system(void);
Expand Down
2 changes: 2 additions & 0 deletions toxcore/tox_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define C_TOXCORE_TOXCORE_TOX_STRUCT_H

#include "Messenger.h"
#include "mem.h"
#include "tox.h"
#include "tox_private.h"

Expand All @@ -19,6 +20,7 @@ struct Tox {
Mono_Time *mono_time;
Random rng;
Network ns;
Memory mem;
pthread_mutex_t *mutex;

tox_log_cb *log_callback;
Expand Down

0 comments on commit ac03d7d

Please sign in to comment.