Merge commit '8eb4892b4976e82e020d0e30dcf8f0705b76bb4e'

This commit is contained in:
2024-01-12 21:30:48 +01:00
126 changed files with 1556 additions and 2484 deletions

View File

@ -1,26 +1,33 @@
# For coverage tests
target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
# Override network and random functions
add_library(fuzz_support func_conversion.h fuzz_support.cc fuzz_support.h)
set(LIBFUZZER_LINKER_FLAGS)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(LIBFUZZER_LINKER_FLAGS "-fsanitize=fuzzer")
else()
message(SEND_ERROR "Compiler must be Clang to build fuzz targets")
endif()
function(fuzz_test target source_dir)
set(${target}_CORPUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/toktok-fuzzer/corpus/${target}_fuzz_test)
file(GLOB ${target}_fuzz_CORPUS "${${target}_CORPUS_DIR}/*")
add_executable(${target}_fuzz_test ${source_dir}/${target}_fuzz_test.cc)
target_link_libraries(${target}_fuzz_test PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})
if(${target}_fuzz_CORPUS)
add_test(NAME ${target}_fuzz COMMAND ${CROSSCOMPILING_EMULATOR} ${target}_fuzz_test -max_total_time=10 ${${target}_fuzz_CORPUS})
endif()
endfunction()
# Fuzzes the toxsave API
add_executable(toxsave_fuzzer toxsave_harness.cc)
target_link_libraries(toxsave_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
target_link_libraries(toxsave_fuzzer PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})
# Fuzzes the bootstrap process
add_executable(bootstrap_fuzzer bootstrap_harness.cc)
target_link_libraries(bootstrap_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
target_link_libraries(bootstrap_fuzzer PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})
add_executable(DHT_fuzz_test ../../toxcore/DHT_fuzz_test.cc)
target_link_libraries(DHT_fuzz_test PRIVATE 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 PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
fuzz_test(DHT ../../toxcore)
fuzz_test(forwarding ../../toxcore)
fuzz_test(group_announce ../../toxcore)
fuzz_test(group_moderation ../../toxcore)
fuzz_test(tox_events ../../toxcore)

View File

@ -126,7 +126,7 @@ void TestBootstrap(Fuzz_Data &input)
}
});
CONSUME1_OR_RETURN(const uint8_t proxy_type, input);
CONSUME1_OR_RETURN(const uint8_t, proxy_type, input);
if (proxy_type == 0) {
tox_options_set_proxy_type(opts.get(), TOX_PROXY_TYPE_NONE);
} else if (proxy_type == 1) {
@ -139,7 +139,7 @@ void TestBootstrap(Fuzz_Data &input)
tox_options_set_proxy_port(opts.get(), 8080);
}
CONSUME1_OR_RETURN(const uint8_t tcp_relay_enabled, input);
CONSUME1_OR_RETURN(const uint8_t, tcp_relay_enabled, input);
if (tcp_relay_enabled >= (UINT8_MAX / 2)) {
tox_options_set_tcp_port(opts.get(), 33445);
}

View File

@ -8,6 +8,7 @@
#include <fstream>
#include <vector>
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/tox.h"
#include "../../toxcore/tox_dispatch.h"
#include "../../toxcore/tox_events.h"

View File

@ -30,6 +30,16 @@ struct Network_Addr {
size_t size;
};
System::System(std::unique_ptr<Tox_System> in_sys, std::unique_ptr<Memory> in_mem,
std::unique_ptr<Network> in_ns, std::unique_ptr<Random> in_rng)
: sys(std::move(in_sys))
, mem(std::move(in_mem))
, ns(std::move(in_ns))
, rng(std::move(in_rng))
{
}
System::System(System &&) = default;
System::~System() { }
static int recv_common(Fuzz_Data &input, uint8_t *buf, size_t buf_len)
@ -67,7 +77,7 @@ static int recv_common(Fuzz_Data &input, uint8_t *buf, size_t buf_len)
template <typename F>
static void *alloc_common(Fuzz_Data &data, F func)
{
CONSUME1_OR_RETURN_VAL(const uint8_t want_alloc, data, func());
CONSUME1_OR_RETURN_VAL(const uint8_t, want_alloc, data, func());
if (!want_alloc) {
return nullptr;
}

View File

@ -7,11 +7,12 @@
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <memory>
#include <vector>
#include <unordered_map>
#include <utility>
#include <vector>
#include "../../toxcore/tox.h"
@ -20,19 +21,28 @@ struct Fuzz_Data {
std::size_t size;
Fuzz_Data(const uint8_t *input_data, std::size_t input_size)
: data(input_data), size(input_size)
{}
: data(input_data)
, size(input_size)
{
}
Fuzz_Data &operator=(const Fuzz_Data &rhs) = delete;
Fuzz_Data(const Fuzz_Data &rhs) = delete;
uint8_t consume1()
{
const uint8_t val = data[0];
++data;
--size;
return val;
}
struct Consumer {
Fuzz_Data &fd;
template <typename T>
operator T()
{
const uint8_t *bytes = fd.consume(sizeof(T));
T val;
std::memcpy(&val, bytes, sizeof(T));
return val;
}
};
Consumer consume1() { return Consumer{*this}; }
const uint8_t *consume(std::size_t count)
{
@ -50,14 +60,14 @@ struct Fuzz_Data {
*
* @example
* @code
* CONSUME1_OR_RETURN(const uint8_t one_byte, input);
* CONSUME1_OR_RETURN(const uint8_t, one_byte, input);
* @endcode
*/
#define CONSUME1_OR_RETURN(DECL, INPUT) \
if (INPUT.size < 1) { \
return; \
} \
DECL = INPUT.consume1()
#define CONSUME1_OR_RETURN(TYPE, NAME, INPUT) \
if (INPUT.size < sizeof(TYPE)) { \
return; \
} \
TYPE NAME = INPUT.consume1()
/** @brief Consumes 1 byte of the fuzzer input or returns a value if no data
* available.
@ -70,11 +80,11 @@ struct Fuzz_Data {
* CONSUME1_OR_RETURN_VAL(const uint8_t one_byte, input, nullptr);
* @endcode
*/
#define CONSUME1_OR_RETURN_VAL(DECL, INPUT, VAL) \
if (INPUT.size < 1) { \
return VAL; \
} \
DECL = INPUT.consume1()
#define CONSUME1_OR_RETURN_VAL(TYPE, NAME, INPUT, VAL) \
if (INPUT.size < sizeof(TYPE)) { \
return VAL; \
} \
TYPE NAME = INPUT.consume1()
/** @brief Consumes SIZE bytes of the fuzzer input or returns if not enough data available.
*
@ -93,6 +103,12 @@ struct Fuzz_Data {
} \
DECL = INPUT.consume(SIZE)
#define CONSUME_OR_RETURN_VAL(DECL, INPUT, SIZE, VAL) \
if (INPUT.size < SIZE) { \
return VAL; \
} \
DECL = INPUT.consume(SIZE)
inline void fuzz_select_target(uint8_t selector, Fuzz_Data &input)
{
// The selector selected no function, so we do nothing and rely on the
@ -100,7 +116,7 @@ inline void fuzz_select_target(uint8_t selector, Fuzz_Data &input)
}
template <typename Arg, typename... Args>
void fuzz_select_target(uint8_t selector, Fuzz_Data &input, Arg &&fn, Args &&... args)
void fuzz_select_target(uint8_t selector, Fuzz_Data &input, Arg &&fn, Args &&...args)
{
if (selector == sizeof...(Args)) {
return fn(input);
@ -109,11 +125,11 @@ void fuzz_select_target(uint8_t selector, Fuzz_Data &input, Arg &&fn, Args &&...
}
template <typename... Args>
void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&... args)
void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&...args)
{
Fuzz_Data input{data, size};
CONSUME1_OR_RETURN(uint8_t selector, input);
CONSUME1_OR_RETURN(const uint8_t, selector, input);
return fuzz_select_target(selector, input, std::forward<Args>(args)...);
}
@ -127,6 +143,10 @@ struct System {
std::unique_ptr<Network> ns;
std::unique_ptr<Random> rng;
System(std::unique_ptr<Tox_System> sys, std::unique_ptr<Memory> mem,
std::unique_ptr<Network> ns, std::unique_ptr<Random> rng);
System(System &&);
// Not inline because sizeof of the above 2 structs is not known everywhere.
~System();

View File

@ -1,96 +1,17 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022 The TokTok team.
* Copyright © 2022-2024 The TokTok team.
*/
#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H
#define C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H
#include <cassert>
#include <memory>
#include "../../toxcore/DHT.h"
#include "../../toxcore/logger.h"
#include "../../toxcore/network.h"
#include "fuzz_support.h"
constexpr uint16_t SIZE_IP_PORT = SIZE_IP6 + sizeof(uint16_t);
template <typename T>
using Ptr = std::unique_ptr<T, void (*)(T *)>;
/** @brief Construct any Tox resource using fuzzer input data.
*
* Constructs (or fails by returning) a valid object of type T and passes it to
* a function specified on the rhs of `>>`. Takes care of cleaning up the
* resource after the specified function returns.
*
* Some `with` instances require additional inputs such as the `Fuzz_Data`
* reference or a logger.
*/
template <typename T>
struct with;
/** @brief Construct a Logger without logging callback.
*/
template <>
struct with<Logger> {
template <typename F>
void operator>>(F &&f)
{
Ptr<Logger> logger(logger_new(), logger_kill);
assert(logger != nullptr);
f(std::move(logger));
}
};
/** @brief Construct an IP_Port by unpacking fuzzer input with `unpack_ip_port`.
*/
template <>
struct with<IP_Port> {
Fuzz_Data &input_;
template <typename F>
void operator>>(F &&f)
{
CONSUME_OR_RETURN(const uint8_t *ipp_packed, input_, SIZE_IP_PORT);
IP_Port ipp;
unpack_ip_port(&ipp, ipp_packed, SIZE_IP6, true);
f(ipp);
}
};
/** @brief Construct a Networking_Core object using the Network vtable passed.
*
* Use `with<Logger>{} >> with<Networking_Core>{input, ns, mem} >> ...` to construct
* a logger and pass it to the Networking_Core constructor function.
*/
template <>
struct with<Networking_Core> {
Fuzz_Data &input_;
const Network *ns_;
const Memory *mem_;
Ptr<Logger> logger_{nullptr, logger_kill};
friend with operator>>(with<Logger> f, with self)
{
f >> [&self](Ptr<Logger> logger) { self.logger_ = std::move(logger); };
return self;
}
template <typename F>
void operator>>(F &&f)
{
with<IP_Port>{input_} >> [&f, this](const IP_Port &ipp) {
Ptr<Networking_Core> net(
new_networking_ex(logger_.get(), mem_, ns_, &ipp.ip, ipp.port, ipp.port + 100, nullptr),
kill_networking);
if (net == nullptr) {
return;
}
f(std::move(net));
};
}
};
#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_TOX_H

View File

@ -1,6 +1,7 @@
#include <cassert>
#include <cstdio>
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/tox.h"
#include "../../toxcore/tox_dispatch.h"
#include "../../toxcore/tox_events.h"