From cb34fe12d13a3e00b4324052921a72d22855dd1d Mon Sep 17 00:00:00 2001 From: iphydf Date: Sat, 2 Apr 2022 17:10:09 +0000 Subject: [PATCH] test: Add more functionality to the bootstrap harness. Ideally this would be able to reach some of the events, so we can write code to respond to those events, but so far only the friend request event actually happens. --- .../docker/tox-bootstrapd.sha256 | 2 +- testing/fuzzing/BUILD.bazel | 16 ++- testing/fuzzing/CMakeLists.txt | 10 +- testing/fuzzing/bootstrap_harness.cc | 136 ++++++++++++++++-- testing/fuzzing/fuzz_adapter.c | 89 ------------ testing/fuzzing/fuzz_adapter.h | 44 ------ testing/fuzzing/fuzz_support.cc | 124 +++++++++++++++- testing/fuzzing/fuzz_support.h | 14 +- testing/fuzzing/toxsave_harness.cc | 26 +++- toxcore/BUILD.bazel | 5 +- toxcore/ccompat.h | 2 - toxcore/crypto_core.c | 84 ++++++----- toxcore/network.c | 109 ++++---------- 13 files changed, 362 insertions(+), 299 deletions(-) delete mode 100644 testing/fuzzing/fuzz_adapter.c delete mode 100644 testing/fuzzing/fuzz_adapter.h diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index ac5852d8..deea421d 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -39a74721e1730757bdb96020acebe25bafb450a4298e4bc9556e3ad2d59260b1 /usr/local/bin/tox-bootstrapd +7c43e683316530c0e9c46df4e670465b887f2a0c0774ee1dc67e4b0e1ca20a35 /usr/local/bin/tox-bootstrapd diff --git a/testing/fuzzing/BUILD.bazel b/testing/fuzzing/BUILD.bazel index 87cd5725..1135a72c 100644 --- a/testing/fuzzing/BUILD.bazel +++ b/testing/fuzzing/BUILD.bazel @@ -1,19 +1,18 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") -cc_library( - name = "fuzz_adapter", - srcs = ["fuzz_adapter.c"], - hdrs = ["fuzz_adapter.h"], - visibility = ["//c-toxcore:__subpackages__"], -) +package(features = ["layering_check"]) cc_library( name = "fuzz_support", srcs = ["fuzz_support.cc"], hdrs = ["fuzz_support.h"], visibility = ["//c-toxcore:__subpackages__"], - deps = ["//c-toxcore/toxcore:tox"], + deps = [ + "//c-toxcore/toxcore:crypto_core", + "//c-toxcore/toxcore:network", + "//c-toxcore/toxcore:tox", + ], ) cc_library( @@ -31,6 +30,9 @@ cc_fuzz_test( deps = [ ":fuzz_support", "//c-toxcore/toxcore:tox", + "//c-toxcore/toxcore:tox_dispatch", + "//c-toxcore/toxcore:tox_events", + "//c-toxcore/toxcore:util", ], ) diff --git a/testing/fuzzing/CMakeLists.txt b/testing/fuzzing/CMakeLists.txt index 588c1301..5c00c764 100644 --- a/testing/fuzzing/CMakeLists.txt +++ b/testing/fuzzing/CMakeLists.txt @@ -2,7 +2,7 @@ target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION") # Override network and random functions -add_library(fuzz_adapter fuzz_adapter.c fuzz_support.cc fuzz_support.h) +add_library(fuzz_support fuzz_support.cc fuzz_support.h) set(LIBFUZZER_LINKER_FLAGS) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") @@ -13,14 +13,14 @@ endif() # Fuzzes the toxsave API add_executable(toxsave_fuzzer toxsave_harness.cc) -target_link_libraries(toxsave_fuzzer toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(toxsave_fuzzer toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) # Fuzzes the bootstrap process add_executable(bootstrap_fuzzer bootstrap_harness.cc) -target_link_libraries(bootstrap_fuzzer toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(bootstrap_fuzzer toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) add_executable(DHT_fuzz_test ../../toxcore/DHT_fuzz_test.cc) -target_link_libraries(DHT_fuzz_test toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(DHT_fuzz_test toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) add_executable(tox_events_fuzz_test ../../toxcore/tox_events_fuzz_test.cc) -target_link_libraries(tox_events_fuzz_test toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(tox_events_fuzz_test toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) diff --git a/testing/fuzzing/bootstrap_harness.cc b/testing/fuzzing/bootstrap_harness.cc index 49869e29..51ab52db 100644 --- a/testing/fuzzing/bootstrap_harness.cc +++ b/testing/fuzzing/bootstrap_harness.cc @@ -3,23 +3,124 @@ #include #include "../../toxcore/tox.h" +#include "../../toxcore/tox_dispatch.h" +#include "../../toxcore/tox_events.h" #include "../../toxcore/tox_private.h" -#include "fuzz_adapter.h" +#include "../../toxcore/tox_struct.h" +#include "../../toxcore/util.h" #include "fuzz_support.h" +namespace { + +void setup_callbacks(Tox_Dispatch *dispatch) +{ + tox_events_callback_conference_connected( + dispatch, [](Tox *tox, const Tox_Event_Conference_Connected *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_connected( + dispatch, [](Tox *tox, const Tox_Event_Conference_Connected *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_invite( + dispatch, [](Tox *tox, const Tox_Event_Conference_Invite *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_message( + dispatch, [](Tox *tox, const Tox_Event_Conference_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_peer_list_changed(dispatch, + [](Tox *tox, const Tox_Event_Conference_Peer_List_Changed *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_peer_name( + dispatch, [](Tox *tox, const Tox_Event_Conference_Peer_Name *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_title( + dispatch, [](Tox *tox, const Tox_Event_Conference_Title *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_chunk_request( + dispatch, [](Tox *tox, const Tox_Event_File_Chunk_Request *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv( + dispatch, [](Tox *tox, const Tox_Event_File_Recv *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv_chunk( + dispatch, [](Tox *tox, const Tox_Event_File_Recv_Chunk *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv_control( + dispatch, [](Tox *tox, const Tox_Event_File_Recv_Control *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_connection_status( + dispatch, [](Tox *tox, const Tox_Event_Friend_Connection_Status *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_lossless_packet( + dispatch, [](Tox *tox, const Tox_Event_Friend_Lossless_Packet *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_lossy_packet( + dispatch, [](Tox *tox, const Tox_Event_Friend_Lossy_Packet *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_message( + dispatch, [](Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_name( + dispatch, [](Tox *tox, const Tox_Event_Friend_Name *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_read_receipt( + dispatch, [](Tox *tox, const Tox_Event_Friend_Read_Receipt *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_request( + dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) { + Tox_Err_Friend_Add err; + tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); + assert(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY + || err == TOX_ERR_FRIEND_ADD_ALREADY_SENT + || err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM); + }); + tox_events_callback_friend_status( + dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_status_message( + dispatch, [](Tox *tox, const Tox_Event_Friend_Status_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_typing( + dispatch, [](Tox *tox, const Tox_Event_Friend_Typing *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_self_connection_status( + dispatch, [](Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data) { + assert(event == nullptr); + }); +} + +} + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - network_adapter_init(data, size); + Fuzz_Data input{data, size}; - uint64_t clock = 0; - auto sys = fuzz_system(clock); - assert(sys->mono_time_callback != nullptr); - assert(sys->mono_time_user_data != nullptr); + Fuzz_System sys(input); + assert(sys.rng != nullptr); Tox_Options *opts = tox_options_new(nullptr); assert(opts != nullptr); - tox_options_set_operating_system(opts, sys.get()); + tox_options_set_operating_system(opts, sys.sys.get()); Tox_Err_New error_new; Tox *tox = tox_new(opts, &error_new); @@ -34,19 +135,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) const bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr); assert(success); - /* - * The iteration count here is a magic value in the literal sense, too small - * and coverage will be bad, too big and fuzzing will not be efficient. - * NOTE: This should be fine tuned after gathering some experience. - */ + tox_events_init(tox); - for (uint32_t i = 0; i < 50; ++i) { - tox_iterate(tox, nullptr); + Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); + assert(dispatch != nullptr); + setup_callbacks(dispatch); + + while (input.size > 0) { + Tox_Err_Events_Iterate error_iterate; + Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); + assert(tox_events_equal(events, events)); + tox_dispatch_invoke(dispatch, events, tox, nullptr); + tox_events_free(events); // Move the clock forward a decent amount so all the time-based checks // trigger more quickly. - clock += 200; + sys.clock += 200; } + tox_dispatch_free(dispatch); tox_kill(tox); return 0; // Non-zero return values are reserved for future use. } diff --git a/testing/fuzzing/fuzz_adapter.c b/testing/fuzzing/fuzz_adapter.c deleted file mode 100644 index 82fd6453..00000000 --- a/testing/fuzzing/fuzz_adapter.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "fuzz_adapter.h" - -struct fuzz_buf { - /* Fuzz data buffer */ - const uint8_t *cur; - const uint8_t *end; -}; - -static struct fuzz_buf data; - -#include -#include -#include - - -void network_adapter_init(const uint8_t *buf, size_t length) -{ - data.cur = buf; - data.end = buf + length; -} - -ssize_t fuzz_sendto(int sockfd, const void *buf, size_t len, - int flags, const struct sockaddr *addr, - socklen_t addrlen) -{ - return len; -} - -ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) -{ - return len; -} - -static ssize_t recv_common(void *buf, size_t buf_len) -{ - if (data.cur + 2 >= data.end) { - return -1; - } - - uint16_t fuzz_len = (data.cur[0] << 8) | data.cur[1]; - data.cur += 2; - - size_t available = data.end - data.cur; - - size_t res = fuzz_len > available ? available : fuzz_len; - res = buf_len > res ? res : buf_len; - - memcpy(buf, data.cur, res); - data.cur += res; - - return res; -} - -ssize_t fuzz_recvfrom(int sockfd, void *buf, size_t len, - int flags, struct sockaddr *src_addr, - socklen_t *addr_len) -{ - if (src_addr && addr_len && (sizeof(struct sockaddr) <= *addr_len)) { - *src_addr = (struct sockaddr) { - 0 - }; - // Dummy Addr - src_addr->sa_family = AF_INET; - - // We want an AF_INET address with dummy values - struct sockaddr_in *addr_in = (struct sockaddr_in *)(void *)src_addr; - addr_in->sin_port = 12356; - addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1; - *addr_len = sizeof(struct sockaddr); - } - - return recv_common(buf, len); -} - -ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags) -{ - return recv_common(buf, len); -} - -void fuzz_random_bytes(uint8_t *rnd, size_t length) -{ - // Amount of data is limited - size_t available = data.end - data.cur; - size_t bytes_read = length > available ? available : length; - // Initialize everything to make MSAN and others happy - memset(rnd, 0, length); - memcpy(rnd, data.cur, bytes_read); - data.cur += bytes_read; -} diff --git a/testing/fuzzing/fuzz_adapter.h b/testing/fuzzing/fuzz_adapter.h deleted file mode 100644 index 91fdbc76..00000000 --- a/testing/fuzzing/fuzz_adapter.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2021 The TokTok team. - */ - -#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H -#define C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Init function for the fuzzing harness - * @param buf Begin of fuzz data - * @param length Length of buf - */ -void network_adapter_init(const uint8_t *buf, size_t length); - -/* The following functions intercept calls to standard network functions for fuzzing purposes and return data from the fuzz buffer. */ - -ssize_t fuzz_sendto(int sockfd, const void *buf, size_t len, - int flags, const struct sockaddr *addr, - socklen_t addrlen); - -ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags); - -ssize_t fuzz_recvfrom(int sockfd, void *buf, size_t len, - int flags, struct sockaddr *src_addr, - socklen_t *addr_len); - -ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags); - -/* The following functions intercept generation of random data */ -void fuzz_random_bytes(uint8_t *rnd, size_t length); - -#ifdef __cplusplus -} -#endif - -#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H diff --git a/testing/fuzzing/fuzz_support.cc b/testing/fuzzing/fuzz_support.cc index b3e8ed32..21a3b310 100644 --- a/testing/fuzzing/fuzz_support.cc +++ b/testing/fuzzing/fuzz_support.cc @@ -4,18 +4,128 @@ #include "fuzz_support.h" +#include +#include + +#include +#include #include #include "../../toxcore/crypto_core.h" #include "../../toxcore/network.h" #include "../../toxcore/tox_private.h" -std::unique_ptr fuzz_system(uint64_t &clock) +// TODO(iphydf): Put this somewhere shared. +struct Network_Addr { + struct sockaddr_storage addr; + size_t size; +}; + +static int recv_common(Fuzz_Data &input, void *buf, size_t buf_len) { - auto sys = std::make_unique(); - sys->mono_time_callback = [](void *user_data) { return *static_cast(user_data); }; - sys->mono_time_user_data = &clock; - sys->rng = system_random(); // TODO(iphydf): Put fuzz_random here. - sys->ns = system_network(); // TODO(iphydf): Put fuzz_network here. - return sys; + if (input.size < 2) { + return -1; + } + + const size_t fuzz_len = (input.data[0] << 8) | input.data[1]; + input.data += 2; + input.size -= 2; + + const size_t res = std::min(buf_len, std::min(fuzz_len, input.size)); + + memcpy(buf, input.data, res); + input.data += res; + input.size -= res; + + return res; } + +static const Network_Funcs fuzz_network_funcs = { + .close = [](void *obj, int sock) { return 0; }, + .accept = [](void *obj, int sock) { return 2; }, + .bind = [](void *obj, int sock, const Network_Addr *addr) { return 0; }, + .listen = [](void *obj, int sock, int backlog) { return 0; }, + .recvbuf = + [](void *obj, int sock) { + // TODO(iphydf): Return something sensible here (from the fuzzer): number of + // bytes to be read from the socket. + return 0; + }, + .recv = + [](void *obj, int sock, uint8_t *buf, size_t len) { + // Receive data from the fuzzer. + return recv_common(static_cast(obj)->data, buf, len); + }, + .recvfrom = + [](void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) { + addr->addr = sockaddr_storage{}; + // Dummy Addr + addr->addr.ss_family = AF_INET; + + // We want an AF_INET address with dummy values + sockaddr_in *addr_in = reinterpret_cast(&addr->addr); + addr_in->sin_port = 12356; + addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1; + addr->size = sizeof(struct sockaddr); + + return recv_common(static_cast(obj)->data, buf, len); + }, + .send = + [](void *obj, int sock, const uint8_t *buf, size_t len) { + // Always succeed. + return static_cast(len); + }, + .sendto = + [](void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) { + // Always succeed. + return static_cast(len); + }, + .socket = [](void *obj, int domain, int type, int proto) { return 1; }, + .socket_nonblock = [](void *obj, int sock, bool nonblock) { return 0; }, + .getsockopt = + [](void *obj, int sock, int level, int optname, void *optval, size_t *optlen) { + memset(optval, 0, *optlen); + return 0; + }, + .setsockopt = [](void *obj, int sock, int level, int optname, const void *optval, + size_t optlen) { return 0; }, +}; + +static const Random_Funcs fuzz_random_funcs = { + .random_bytes = + [](void *obj, uint8_t *bytes, size_t length) { + Fuzz_System *sys = static_cast(obj); + // Amount of data is limited + const size_t available = sys->data.size; + const size_t bytes_read = std::min(length, available); + // Initialize everything to make MSAN and others happy + std::memset(bytes, 0, length); + std::memcpy(bytes, sys->data.data, bytes_read); + sys->data.data += bytes_read; + sys->data.size -= bytes_read; + }, + .random_uniform = + [](void *obj, uint32_t upper_bound) { + Fuzz_System *sys = static_cast(obj); + uint32_t randnum; + sys->rng->funcs->random_bytes( + sys, reinterpret_cast(&randnum), sizeof(randnum)); + return randnum % upper_bound; + }, +}; + +Fuzz_System::Fuzz_System(Fuzz_Data &input) + : clock(0) + , data(input) + , sys(std::make_unique()) + , ns(std::make_unique(Network{&fuzz_network_funcs, this})) + , rng(std::make_unique(Random{&fuzz_random_funcs, this})) +{ + sys->mono_time_callback + = [](void *user_data) { return static_cast(user_data)->clock; }; + sys->mono_time_user_data = this; + sys->ns = ns.get(); + sys->rng = rng.get(); +} + +Fuzz_System::~Fuzz_System() { } diff --git a/testing/fuzzing/fuzz_support.h b/testing/fuzzing/fuzz_support.h index a8a1d8da..b25a8076 100644 --- a/testing/fuzzing/fuzz_support.h +++ b/testing/fuzzing/fuzz_support.h @@ -97,6 +97,18 @@ void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&... args) return fuzz_select_target(selector, input, std::forward(args)...); } -std::unique_ptr fuzz_system(uint64_t &clock); +struct Network; +struct Random; + +struct Fuzz_System { + uint64_t clock; + Fuzz_Data &data; + std::unique_ptr sys; + std::unique_ptr ns; + std::unique_ptr rng; + + Fuzz_System(Fuzz_Data &input); + ~Fuzz_System(); +}; #endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H diff --git a/testing/fuzzing/toxsave_harness.cc b/testing/fuzzing/toxsave_harness.cc index 068c9d9a..31b41a88 100644 --- a/testing/fuzzing/toxsave_harness.cc +++ b/testing/fuzzing/toxsave_harness.cc @@ -6,8 +6,9 @@ #include "../../toxcore/tox_private.h" #include "fuzz_support.h" -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +namespace { + +void TestSaveDataLoading(Fuzz_Data &input) { Tox_Err_Options_New error_options; @@ -16,19 +17,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) assert(tox_options != nullptr); assert(error_options == TOX_ERR_OPTIONS_NEW_OK); - uint64_t clock = 0; - auto sys = fuzz_system(clock); - tox_options_set_operating_system(tox_options, sys.get()); + const size_t savedata_size = input.size; + CONSUME_OR_RETURN(const uint8_t *savedata, input, savedata_size); + + Fuzz_System sys(input); + tox_options_set_operating_system(tox_options, sys.sys.get()); // pass test data to Tox - tox_options_set_savedata_data(tox_options, data, size); + tox_options_set_savedata_data(tox_options, savedata, savedata_size); tox_options_set_savedata_type(tox_options, TOX_SAVEDATA_TYPE_TOX_SAVE); Tox *tox = tox_new(tox_options, nullptr); tox_options_free(tox_options); if (tox == nullptr) { // Tox save was invalid, we're finished here - return 0; + return; } // verify that the file can be saved again @@ -36,5 +39,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) tox_get_savedata(tox, new_savedata.data()); tox_kill(tox); +} + +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + Fuzz_Data input{data, size}; + TestSaveDataLoading(input); return 0; // Non-zero return values are reserved for future use. } diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 0656707d..ffe2ff5f 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -64,7 +64,6 @@ cc_library( visibility = ["//c-toxcore:__subpackages__"], deps = [ ":ccompat", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@libsodium", ], ) @@ -136,7 +135,6 @@ cc_library( ], deps = [ ":ccompat", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@pthread", ], ) @@ -160,6 +158,7 @@ cc_library( "//c-toxcore/auto_tests:__pkg__", "//c-toxcore/other:__pkg__", "//c-toxcore/other/bootstrap_daemon:__pkg__", + "//c-toxcore/testing/fuzzing:__pkg__", "//c-toxcore/toxav:__pkg__", ], deps = [ @@ -178,6 +177,7 @@ cc_library( "//c-toxcore/auto_tests:__pkg__", "//c-toxcore/other:__pkg__", "//c-toxcore/other/bootstrap_daemon:__pkg__", + "//c-toxcore/testing/fuzzing:__pkg__", "//c-toxcore/toxav:__pkg__", ], deps = [ @@ -186,7 +186,6 @@ cc_library( ":logger", ":mono_time", ":util", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@libsodium", "@psocket", "@pthread", diff --git a/toxcore/ccompat.h b/toxcore/ccompat.h index 8cd2844c..9ea6739a 100644 --- a/toxcore/ccompat.h +++ b/toxcore/ccompat.h @@ -12,8 +12,6 @@ #include "attributes.h" -/* No declarations here. */ - //!TOKSTYLE- // Variable length arrays. diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 5b360bdc..ccfda08d 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -40,12 +40,6 @@ #define ENC_SECRET_KEY_SIZE CRYPTO_SECRET_KEY_SIZE #endif -//!TOKSTYLE- -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -#include "../testing/fuzzing/fuzz_adapter.h" -#endif -//!TOKSTYLE+ - static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES, "CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES"); static_assert(CRYPTO_SECRET_KEY_SIZE == crypto_box_SECRETKEYBYTES, @@ -122,38 +116,38 @@ static void crypto_free(uint8_t *ptr, size_t bytes) void crypto_memzero(void *data, size_t length) { -#ifndef VANILLA_NACL - sodium_memzero(data, length); -#else +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) memset(data, 0, length); +#else + sodium_memzero(data, length); #endif } bool crypto_memlock(void *data, size_t length) { -#ifndef VANILLA_NACL +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) + return false; +#else if (sodium_mlock(data, length) != 0) { return false; } return true; -#else - return false; #endif } bool crypto_memunlock(void *data, size_t length) { -#ifndef VANILLA_NACL +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) + return false; +#else if (sodium_munlock(data, length) != 0) { return false; } return true; -#else - return false; #endif } @@ -169,18 +163,26 @@ bool public_key_eq(const uint8_t *pk1, const uint8_t *pk2) bool crypto_sha512_eq(const uint8_t *cksum1, const uint8_t *cksum2) { -#ifndef VANILLA_NACL - return crypto_verify_64(cksum1, cksum2) == 0; -#else +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + // Hope that this is better for the fuzzer + return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0; +#elif defined(VANILLA_NACL) const int lo = crypto_verify_32(cksum1, cksum2) == 0 ? 1 : 0; const int hi = crypto_verify_32(cksum1 + 8, cksum2 + 8) == 0 ? 1 : 0; return (lo & hi) == 1; +#else + return crypto_verify_64(cksum1, cksum2) == 0; #endif } bool crypto_sha256_eq(const uint8_t *cksum1, const uint8_t *cksum2) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // Hope that this is better for the fuzzer + return memcmp(cksum1, cksum2, CRYPTO_SHA256_SIZE) == 0; +#else return crypto_verify_32(cksum1, cksum2) == 0; +#endif } uint8_t random_u08(const Random *rng) @@ -238,17 +240,19 @@ bool crypto_signature_verify(const uint8_t *signature, const uint8_t *message, u bool public_key_valid(const uint8_t *public_key) { - if (public_key[31] >= 128) { /* Last bit of key is always zero. */ - return false; - } - - return true; + /* Last bit of key is always zero. */ + return public_key[31] < 128; } int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE); + return 0; +#else return crypto_box_beforenm(shared_key, public_key, secret_key); +#endif } int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, @@ -450,11 +454,6 @@ void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key) crypto_scalarmult_curve25519_base(public_key, secret_key); } -void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length) -{ - crypto_hash_sha256(hash, data, length); -} - void new_hmac_key(const Random *rng, uint8_t *key) { random_bytes(rng, key, CRYPTO_HMAC_KEY_SIZE); @@ -472,31 +471,42 @@ bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[ return crypto_auth_verify(auth, data, length, key) == 0; } +void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length) +{ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memset(hash, 0, CRYPTO_SHA256_SIZE); + memcpy(hash, data, length < CRYPTO_SHA256_SIZE ? length : CRYPTO_SHA256_SIZE); +#else + crypto_hash_sha256(hash, data, length); +#endif +} + void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memset(hash, 0, CRYPTO_SHA512_SIZE); + memcpy(hash, data, length < CRYPTO_SHA512_SIZE ? length : CRYPTO_SHA512_SIZE); +#else crypto_hash_sha512(hash, data, length); +#endif } non_null() static void sys_random_bytes(void *obj, uint8_t *bytes, size_t length) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - fuzz_random_bytes(bytes, length); -#else randombytes(bytes, length); -#endif } non_null() static uint32_t sys_random_uniform(void *obj, uint32_t upper_bound) { -#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) +#ifdef VANILLA_NACL uint32_t randnum; sys_random_bytes(obj, (uint8_t *)&randnum, sizeof(randnum)); return randnum % upper_bound; #else return randombytes_uniform(upper_bound); -#endif // VANILLA_NACL +#endif } static const Random_Funcs system_random_funcs = { @@ -508,6 +518,11 @@ static const Random system_random_obj = {&system_random_funcs}; const Random *system_random(void) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if ((true)) { + return nullptr; + } +#endif #ifndef VANILLA_NACL // It is safe to call this function more than once and from different // threads -- subsequent calls won't have any effects. @@ -515,7 +530,6 @@ const Random *system_random(void) return nullptr; } #endif - return &system_random_obj; } diff --git a/toxcore/network.c b/toxcore/network.c index 10252a9e..f9986f2e 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -97,12 +97,6 @@ #include "mono_time.h" #include "util.h" -//!TOKSTYLE- -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -#include "../testing/fuzzing/fuzz_adapter.h" -#endif -//!TOKSTYLE+ - // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD #if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 @@ -127,12 +121,10 @@ static bool should_ignore_recv_error(int err) return err == EWOULDBLOCK; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION static bool should_ignore_connect_error(int err) { return err == EWOULDBLOCK || err == EINPROGRESS; } -#endif non_null() static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize) @@ -488,54 +480,34 @@ struct Network_Addr { non_null() static int sys_close(void *obj, int sock) { -#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) - return 0; -#elif defined(OS_WIN32) +#if defined(OS_WIN32) return closesocket(sock); #else // !OS_WIN32 return close(sock); -#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#endif } non_null() static int sys_accept(void *obj, int sock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 2; -#else return accept(sock, nullptr, nullptr); -#endif } non_null() static int sys_bind(void *obj, int sock, const Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return bind(sock, (const struct sockaddr *)&addr->addr, addr->size); -#endif } non_null() static int sys_listen(void *obj, int sock, int backlog) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return listen(sock, backlog); -#endif } non_null() static int sys_recvbuf(void *obj, int sock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - // TODO(iphydf): Return something sensible here (from the fuzzer): number of - // bytes to be read from the socket. - return 0; -#else - #ifdef OS_WIN32 u_long count = 0; ioctlsocket(sock, FIONREAD, &count); @@ -545,100 +517,63 @@ static int sys_recvbuf(void *obj, int sock) #endif return count; -#endif } non_null() static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_recv(sock, (char *)buf, len, MSG_NOSIGNAL); -#else return recv(sock, (char *)buf, len, MSG_NOSIGNAL); -#endif } non_null() static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_send(sock, (const char *)buf, len, MSG_NOSIGNAL); -#else return send(sock, (const char *)buf, len, MSG_NOSIGNAL); -#endif } non_null() static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size); -#else return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size); -#endif } non_null() static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - socklen_t size = addr->size; - const int ret = fuzz_recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size); - addr->size = size; - return ret; -#else socklen_t size = addr->size; const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size); addr->size = size; return ret; -#endif } non_null() static int sys_socket(void *obj, int domain, int type, int proto) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 1; -#else return (int)socket(domain, type, proto); -#endif } non_null() static int sys_socket_nonblock(void *obj, int sock, bool nonblock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else #ifdef OS_WIN32 u_long mode = nonblock ? 1 : 0; return ioctlsocket(sock, FIONBIO, &mode); #else return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0); #endif /* OS_WIN32 */ -#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ } non_null() static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - memset(optval, 0, *optlen); - return 0; -#else socklen_t len = *optlen; const int ret = getsockopt(sock, level, optname, optval, &len); *optlen = len; return ret; -#endif } non_null() static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return setsockopt(sock, level, optname, optval, optlen); -#endif } static const Network_Funcs system_network_funcs = { @@ -660,6 +595,11 @@ static const Network system_network_obj = {&system_network_funcs}; const Network *system_network(void) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if ((true)) { + return nullptr; + } +#endif #ifdef OS_WIN32 WSADATA wsaData; @@ -1528,11 +1468,9 @@ bool addr_parse_ip(const char *address, IP *to) return false; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /** addr_resolve return values */ #define TOX_ADDR_RESOLVE_INET 1 #define TOX_ADDR_RESOLVE_INET6 2 -#endif /** * Uses getaddrinfo to resolve an address into an IP address. @@ -1555,8 +1493,10 @@ non_null(1, 2, 3) nullable(4) static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra) { #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else + if ((true)) { + return 0; + } +#endif if (address == nullptr || to == nullptr) { return 0; @@ -1641,7 +1581,6 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr freeaddrinfo(server); return result; -#endif } bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra) @@ -1682,8 +1621,11 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port) } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return addrsize != 0; -#else + if ((true)) { + return true; + } +#endif + Ip_Ntoa ip_str; LOGGER_DEBUG(log, "connecting socket %d to %s:%d", (int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); @@ -1703,20 +1645,22 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port) } return true; -#endif } int32_t net_getipport(const char *node, IP_Port **res, int tox_type) { #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - *res = (IP_Port *)calloc(1, sizeof(IP_Port)); - assert(*res != nullptr); - IP_Port *ip_port = *res; - ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3 - ip_port->ip.family = *make_tox_family(AF_INET); + if ((true)) { + *res = (IP_Port *)calloc(1, sizeof(IP_Port)); + assert(*res != nullptr); + IP_Port *ip_port = *res; + ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3 + ip_port->ip.family = *make_tox_family(AF_INET); + + return 1; + } +#endif - return 1; -#else // Try parsing as IP address first. IP_Port parsed = {{{0}}}; @@ -1805,7 +1749,6 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type) freeaddrinfo(infos); return count; -#endif } void net_freeipport(IP_Port *ip_ports)