Skip to content
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

Restyle refactor: Avoid static_cast in Fuzz_System functions. #2278

Closed
wants to merge 2 commits into from
Closed
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
5 changes: 4 additions & 1 deletion testing/fuzzing/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ package(features = ["layering_check"])

cc_library(
name = "fuzz_support",
srcs = ["fuzz_support.cc"],
srcs = [
"func_conversion.h",
"fuzz_support.cc",
],
hdrs = ["fuzz_support.h"],
visibility = ["//c-toxcore:__subpackages__"],
deps = [
Expand Down
2 changes: 1 addition & 1 deletion testing/fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")

# Override network and random functions
add_library(fuzz_support fuzz_support.cc fuzz_support.h)
add_library(fuzz_support func_conversion.h fuzz_support.cc fuzz_support.h)

set(LIBFUZZER_LINKER_FLAGS)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
Expand Down
63 changes: 63 additions & 0 deletions testing/fuzzing/func_conversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2022 The TokTok team.
*/

#ifndef C_TOXCORE_TESTING_FUZZING_FUNC_CONVERSION_H
#define C_TOXCORE_TESTING_FUZZING_FUNC_CONVERSION_H

namespace detail {

template <typename F, F f>
struct func_conversion {
template <typename R, typename... Args>
using Func = R (*)(Args...);

struct Static_Cast {
void *obj;

template <typename T>
operator T *() const
{
return static_cast<T *>(obj);
}
};

template <typename R, typename... Args>
constexpr operator Func<R, Args...>()
{
return [](void *obj, auto... args) { return f(Static_Cast{obj}, args...); };
}
};

template <typename F>
struct make_funptr;

template <typename T, typename R, typename... Args>
struct make_funptr<R (T::*)(Args...) const> {
using type = R (*)(Args...);
};

/** @brief Turn a memfunptr type into a plain funptr type.
*
* Not needed in C++20, because we can pass the lambda itself as template
* argument, but in C++17, we need to do an early conversion.
*/
template <typename F>
using make_funptr_t = typename make_funptr<F>::type;

}

/** @brief Turn a C++ lambda into a C function pointer with `void*` param.
*
* Takes a lambda function with any pointer type as first parameter and turns it
* into a C function pointer with `void*` as the first parameter. Internally, it
* `static_cast`s that `void*` to the lambda's parameter type, avoiding a bunch
* of casts inside the lambdas.
*/
template <typename F>
static constexpr auto operator!(F f)
{
return detail::func_conversion<detail::make_funptr_t<decltype(&F::operator())>, f>{};
}

#endif // C_TOXCORE_TESTING_FUZZING_FUNC_CONVERSION_H
34 changes: 16 additions & 18 deletions testing/fuzzing/fuzz_support.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "../../toxcore/crypto_core.h"
#include "../../toxcore/network.h"
#include "../../toxcore/tox_private.h"
#include "func_conversion.h"

// TODO(iphydf): Put this somewhere shared.
struct Network_Addr {
Expand All @@ -40,7 +41,7 @@ static int recv_common(Fuzz_Data &input, void *buf, size_t buf_len)
return res;
}

static const Network_Funcs fuzz_network_funcs = {
static constexpr 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; },
Expand All @@ -52,12 +53,12 @@ static const Network_Funcs fuzz_network_funcs = {
return 0;
},
/* .recv = */
[](void *obj, int sock, uint8_t *buf, size_t len) {
![](Fuzz_System *self, int sock, uint8_t *buf, size_t len) {
// Receive data from the fuzzer.
return recv_common(static_cast<Fuzz_System *>(obj)->data, buf, len);
return recv_common(self->data, buf, len);
},
/* .recvfrom = */
[](void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
![](Fuzz_System *self, int sock, uint8_t *buf, size_t len, Network_Addr *addr) {
addr->addr = sockaddr_storage{};
// Dummy Addr
addr->addr.ss_family = AF_INET;
Expand All @@ -68,7 +69,7 @@ static const Network_Funcs fuzz_network_funcs = {
addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1;
addr->size = sizeof(struct sockaddr);

return recv_common(static_cast<Fuzz_System *>(obj)->data, buf, len);
return recv_common(self->data, buf, len);
},
/* .send = */
[](void *obj, int sock, const uint8_t *buf, size_t len) {
Expand All @@ -93,24 +94,22 @@ static const Network_Funcs fuzz_network_funcs = {
},
};

static const Random_Funcs fuzz_random_funcs = {
static constexpr Random_Funcs fuzz_random_funcs = {
/* .random_bytes = */
[](void *obj, uint8_t *bytes, size_t length) {
Fuzz_System *sys = static_cast<Fuzz_System *>(obj);
![](Fuzz_System *self, uint8_t *bytes, size_t length) {
// Amount of data is limited
const size_t available = sys->data.size;
const size_t bytes_read = std::min(length, available);
const size_t bytes_read = std::min(length, self->data.size);
// 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;
std::memcpy(bytes, self->data.data, bytes_read);
self->data.data += bytes_read;
self->data.size -= bytes_read;
},
/* .random_uniform = */
[](void *obj, uint32_t upper_bound) {
Fuzz_System *sys = static_cast<Fuzz_System *>(obj);
![](Fuzz_System *self, uint32_t upper_bound) {
uint32_t randnum;
sys->rng->funcs->random_bytes(sys, reinterpret_cast<uint8_t *>(&randnum), sizeof(randnum));
self->rng->funcs->random_bytes(
self, reinterpret_cast<uint8_t *>(&randnum), sizeof(randnum));
return randnum % upper_bound;
},
};
Expand All @@ -122,8 +121,7 @@ Fuzz_System::Fuzz_System(Fuzz_Data &input)
, ns(std::make_unique<Network>(Network{&fuzz_network_funcs, this}))
, rng(std::make_unique<Random>(Random{&fuzz_random_funcs, this}))
{
sys->mono_time_callback
= [](void *user_data) { return static_cast<Fuzz_System *>(user_data)->clock; };
sys->mono_time_callback = ![](Fuzz_System *self) { return self->clock; };
sys->mono_time_user_data = this;
sys->ns = ns.get();
sys->rng = rng.get();
Expand Down