mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
refactor: Avoid static_cast
in Fuzz_System
functions.
Declutters the fuzz system code a bit, hiding the cast behind a `!` operator.
This commit is contained in:
parent
616bd63021
commit
27c27b7c8c
|
@ -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 = [
|
||||
|
|
|
@ -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")
|
||||
|
|
69
testing/fuzzing/func_conversion.h
Normal file
69
testing/fuzzing/func_conversion.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* 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 {
|
||||
private:
|
||||
template <typename R, typename... Args>
|
||||
using func_pointer = R (*)(Args...);
|
||||
|
||||
template <typename From>
|
||||
struct static_caster {
|
||||
From obj;
|
||||
|
||||
template <typename To>
|
||||
operator To() const
|
||||
{
|
||||
return static_cast<To>(obj);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename R, typename Arg, typename... Args>
|
||||
constexpr operator func_pointer<R, Arg, Args...>()
|
||||
{
|
||||
return [](Arg obj, auto... args) { return f(static_caster<Arg>{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.
|
||||
*
|
||||
* This works on any type `T` that can be `static_cast` to `U`, not just `void*`
|
||||
* to `U*`, but the common case for C callbacks is `void*`.
|
||||
*/
|
||||
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
|
|
@ -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 {
|
||||
|
@ -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; },
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
},
|
||||
};
|
||||
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue
Block a user