8000 test: Add fuzzer support functions for internal toxcore objects. by iphydf · Pull Request #2232 · TokTok/c-toxcore · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

test: Add fuzzer support functions for internal toxcore objects. #2232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions testing/fuzzing/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 = "fuzz_tox",
hdrs = ["fuzz_tox.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = [":fuzz_support"],
)

cc_fuzz_test(
name = "bootstrap_fuzz_test",
srcs = ["bootstrap_harness.cc"],
Expand Down
4 changes: 4 additions & 0 deletions testing/fuzzing/fuzz_support.cc
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2021-2022 The TokTok team.
*/

#include "fuzz_support.h"
44 changes: 27 additions & 17 deletions testing/fuzzing/fuzz_support.h
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2021 The TokTok team.
* Copyright © 2021-2022 The TokTok team.
*/

#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
#define C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H

#include <cstdint>
#include <cstdlib>
#include <utility>

struct Fuzz_Data {
const uint8_t *data;
std::size_t size;

uint8_t consume1() {
Fuzz_Data(const uint8_t *input_data, std::size_t 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;
}

const uint8_t *consume(std::size_t count) {
const uint8_t *consume(std::size_t count)
{
const uint8_t *val = data;
data += count;
size -= count;
Expand All @@ -38,9 +48,9 @@ struct Fuzz_Data {
* @endcode
*/
#define CONSUME1_OR_RETURN(DECL, INPUT) \
if (INPUT.size < 1) { \
return; \
} \
if (INPUT.size < 1) { \
return; \
} \
DECL = INPUT.consume1()

/** @brief Consumes SIZE bytes of the fuzzer input or returns if not enough data available.
Expand All @@ -55,33 +65,33 @@ struct Fuzz_Data {
* @endcode
*/
#define CONSUME_OR_RETURN(DECL, INPUT, SIZE) \
if (INPUT.size < SIZE) { \
return; \
} \
if (INPUT.size < SIZE) { \
return; \
} \
DECL = INPUT.consume(SIZE)

inline void fuzz_select_target(uint8_t selector, Fuzz_Data input)
inline void fuzz_select_target(uint8_t selector, Fuzz_Data &input)
{
// The selector selected no function, so we do nothing and rely on the
// fuzzer to come up with a better selector.
}

template<typename Arg, typename ...Args>
void fuzz_select_target(uint8_t selector, Fuzz_Data input, Arg fn, Args ...args)
template <typename Arg, typename... Args>
void fuzz_select_target(uint8_t selector, Fuzz_Data &input, Arg &&fn, Args &&... args)
{
if (selector == sizeof...(Args)) {
return fn(input);
}
return fuzz_select_target(selector - 1, input, args...);
return fuzz_select_target(selector - 1, input, std::forward<Args>(args)...);
}

template<typename ...Args>
void fuzz_select_target(const uint8_t *data, std::size_t size, Args ...args)
template <typename... 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);
return fuzz_select_target(selector, input, args...);
return fuzz_select_target(selector, input, std::forward<Args>(args)...);
}

#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
95 changes: 95 additions & 0 deletions testing/fuzzing/fuzz_tox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022 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} >> ...` to construct
* a logger and pass it to the Networking_Core constructor function.
*/
template <>
struct with<Networking_Core> {
Fuzz_Data &input_;
const Network *ns_;
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(), 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
4 changes: 2 additions & 2 deletions toxcore/DHT_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace {

void TestHandleRequest(Fuzz_Data input)
void TestHandleRequest(Fuzz_Data &input)
{
CONSUME_OR_RETURN(const uint8_t *self_public_key, input, CRYPTO_PUBLIC_KEY_SIZE);
CONSUME_OR_RETURN(const uint8_t *self_secret_key, input, CRYPTO_SECRET_KEY_SIZE);
Expand All @@ -19,7 +19,7 @@ void TestHandleRequest(Fuzz_Data input)
self_public_key, self_secret_key, public_key, request, &request_id, input.data, input.size);
}

void TestUnpackNodes(Fuzz_Data input)
void TestUnpackNodes(Fuzz_Data &input)
{
CONSUME1_OR_RETURN(const bool tcp_enabled, input);

Expand Down
6 changes: 3 additions & 3 deletions toxcore/group_moderation_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@

namespace {

void TestModListUnpack(Fuzz_Data input)
void TestModListUnpack(Fuzz_Data &input)
{
CONSUME1_OR_RETURN(const uint16_t num_mods, input);
Moderation mods{};
mod_list_unpack(&mods, input.data, input.size, num_mods);
mod_list_cleanup(&mods);
}

void TestSanctionsListUnpack(Fuzz_Data input)
void TestSanctionsListUnpack(Fuzz_Data &input)
{
Mod_Sanction sanctions[10];
Mod_Sanction_Creds creds;
uint16_t processed_data_len;
sanctions_list_unpack(sanctions, &creds, 10, input.data, input.size, &processed_data_len);
}

void TestSanctionCredsUnpack(Fuzz_Data input)
void TestSanctionCredsUnpack(Fuzz_Data &input)
{
CONSUME_OR_RETURN(const uint8_t *data, input, MOD_SANCTIONS_CREDS_SIZE);
Mod_Sanction_Creds creds;
Expand Down
0