mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
test: Add some support functions to make writing fuzzers easier.
This commit is contained in:
parent
96ab8918dc
commit
478ef39b39
|
@ -8,6 +8,13 @@ cc_library(
|
||||||
visibility = ["//c-toxcore:__subpackages__"],
|
visibility = ["//c-toxcore:__subpackages__"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "fuzz_support",
|
||||||
|
srcs = ["fuzz_support.cc"],
|
||||||
|
hdrs = ["fuzz_support.h"],
|
||||||
|
visibility = ["//c-toxcore:__subpackages__"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_fuzz_test(
|
cc_fuzz_test(
|
||||||
name = "bootstrap_fuzzer",
|
name = "bootstrap_fuzzer",
|
||||||
srcs = ["bootstrap_harness.cc"],
|
srcs = ["bootstrap_harness.cc"],
|
||||||
|
|
1
testing/fuzzing/fuzz_support.cc
Normal file
1
testing/fuzzing/fuzz_support.cc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "fuzz_support.h"
|
87
testing/fuzzing/fuzz_support.h
Normal file
87
testing/fuzzing/fuzz_support.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
* Copyright © 2021 The TokTok team.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
|
||||||
|
#define C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
struct Fuzz_Data {
|
||||||
|
const uint8_t *data;
|
||||||
|
std::size_t size;
|
||||||
|
|
||||||
|
uint8_t consume1() {
|
||||||
|
const uint8_t val = data[0];
|
||||||
|
++data;
|
||||||
|
--size;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *consume(std::size_t count) {
|
||||||
|
const uint8_t *val = data;
|
||||||
|
data += count;
|
||||||
|
size -= count;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Consumes 1 byte of the fuzzer input or returns if no data available.
|
||||||
|
*
|
||||||
|
* This advances the fuzzer input data by 1 byte and consumes that byte in the
|
||||||
|
* declaration.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* @code
|
||||||
|
* CONSUME1_OR_RETURN(const uint8_t one_byte, input);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#define CONSUME1_OR_RETURN(DECL, INPUT) \
|
||||||
|
if (INPUT.size < 1) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
DECL = INPUT.consume1()
|
||||||
|
|
||||||
|
/** @brief Consumes SIZE bytes of the fuzzer input or returns if not enough data available.
|
||||||
|
*
|
||||||
|
* This advances the fuzzer input data by SIZE byte and consumes those bytes in
|
||||||
|
* the declaration. If less than SIZE bytes are available in the fuzzer input,
|
||||||
|
* this macro returns from the enclosing function.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* @code
|
||||||
|
* CONSUME_OR_RETURN(const uint8_t *ten_bytes, input, 10);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#define CONSUME_OR_RETURN(DECL, INPUT, SIZE) \
|
||||||
|
if (INPUT.size < SIZE) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
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
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (selector == sizeof...(Args)) {
|
||||||
|
return fn(input);
|
||||||
|
}
|
||||||
|
return fuzz_select_target(selector - 1, input, 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...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H
|
|
@ -299,7 +299,10 @@ cc_fuzz_test(
|
||||||
name = "DHT_fuzz_test",
|
name = "DHT_fuzz_test",
|
||||||
srcs = ["DHT_fuzz_test.cc"],
|
srcs = ["DHT_fuzz_test.cc"],
|
||||||
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
|
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
|
||||||
deps = [":DHT"],
|
deps = [
|
||||||
|
":DHT",
|
||||||
|
"//c-toxcore/testing/fuzzing:fuzz_support",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
|
|
|
@ -3,43 +3,31 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../testing/fuzzing/fuzz_support.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void TestHandleRequest(const uint8_t *input_data, size_t input_size)
|
void TestHandleRequest(Fuzz_Data input)
|
||||||
{
|
{
|
||||||
const uint8_t *data = input_data;
|
CONSUME_OR_RETURN(const uint8_t *self_public_key, input, CRYPTO_PUBLIC_KEY_SIZE);
|
||||||
size_t size = input_size;
|
CONSUME_OR_RETURN(const uint8_t *self_secret_key, input, CRYPTO_SECRET_KEY_SIZE);
|
||||||
|
|
||||||
const uint8_t *self_public_key = data;
|
|
||||||
data += CRYPTO_PUBLIC_KEY_SIZE;
|
|
||||||
size -= CRYPTO_PUBLIC_KEY_SIZE;
|
|
||||||
|
|
||||||
const uint8_t *self_secret_key = data;
|
|
||||||
data += CRYPTO_SECRET_KEY_SIZE;
|
|
||||||
size -= CRYPTO_SECRET_KEY_SIZE;
|
|
||||||
|
|
||||||
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
|
||||||
uint8_t request[MAX_CRYPTO_REQUEST_SIZE];
|
uint8_t request[MAX_CRYPTO_REQUEST_SIZE];
|
||||||
uint8_t request_id;
|
uint8_t request_id;
|
||||||
handle_request(self_public_key, self_secret_key, public_key, request, &request_id, data, size);
|
handle_request(
|
||||||
|
self_public_key, self_secret_key, public_key, request, &request_id, input.data, input.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestUnpackNodes(const uint8_t *input_data, size_t input_size)
|
void TestUnpackNodes(Fuzz_Data input)
|
||||||
{
|
{
|
||||||
const uint8_t *data = input_data;
|
CONSUME1_OR_RETURN(const bool tcp_enabled, input);
|
||||||
size_t size = input_size;
|
|
||||||
|
|
||||||
if (size < 1) {
|
const uint16_t node_count = 5;
|
||||||
return;
|
Node_format nodes[node_count];
|
||||||
}
|
|
||||||
|
|
||||||
const bool tcp_enabled = data[0];
|
|
||||||
++data;
|
|
||||||
--size;
|
|
||||||
|
|
||||||
Node_format nodes[5];
|
|
||||||
uint16_t processed_data_len;
|
uint16_t processed_data_len;
|
||||||
const int packed_count = unpack_nodes(nodes, 5, &processed_data_len, data, size, tcp_enabled);
|
const int packed_count
|
||||||
|
= unpack_nodes(nodes, node_count, &processed_data_len, input.data, input.size, tcp_enabled);
|
||||||
if (packed_count > 0) {
|
if (packed_count > 0) {
|
||||||
Logger *logger = logger_new();
|
Logger *logger = logger_new();
|
||||||
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
|
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
|
||||||
|
@ -53,28 +41,9 @@ void TestUnpackNodes(const uint8_t *input_data, size_t input_size)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *input_data, size_t input_size);
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *input_data, size_t input_size)
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
{
|
{
|
||||||
const uint8_t *data = input_data;
|
fuzz_select_target(data, size, TestHandleRequest, TestUnpackNodes);
|
||||||
size_t size = input_size;
|
return 0;
|
||||||
|
|
||||||
if (size < 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t func = data[0];
|
|
||||||
++data;
|
|
||||||
--size;
|
|
||||||
|
|
||||||
switch (func) {
|
|
||||||
case 0:
|
|
||||||
TestHandleRequest(data, size);
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
TestUnpackNodes(data, size);
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user