test: Add fuzzer tests to the bazel build.

This commit is contained in:
iphydf 2022-03-23 00:46:10 +00:00
parent 7dde71c4e9
commit 1928704065
No known key found for this signature in database
GPG Key ID: 3855DBA2D74403C9
16 changed files with 221 additions and 11 deletions

View File

@ -102,8 +102,8 @@ bazel-valgrind_task:
test_all_script: test_all_script:
- cd /src/workspace && bazel test -k - cd /src/workspace && bazel test -k
--remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST --remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST
--build_tag_filters=-haskell --build_tag_filters=-haskell,-fuzz-test
--test_tag_filters=-haskell --test_tag_filters=-haskell,-fuzz-test
--remote_download_minimal --remote_download_minimal
--config=valgrind --config=valgrind
-- --

View File

@ -8,7 +8,7 @@ AlwaysBreakTemplateDeclarations: Yes
SpaceBeforeCpp11BracedList: false SpaceBeforeCpp11BracedList: false
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
IncludeIsMainRegex: '([-_](test))?$' IncludeIsMainRegex: '([-_](test|fuzz_test))?$'
IncludeBlocks: Regroup IncludeBlocks: Regroup
IncludeCategories: IncludeCategories:
- Regex: '^<.*\.h>' - Regex: '^<.*\.h>'

View File

@ -55,6 +55,7 @@ FIND_QUERY="$FIND_QUERY -and -not -name amalgamation.cc"
FIND_QUERY="$FIND_QUERY -and -not -name av_test.c" FIND_QUERY="$FIND_QUERY -and -not -name av_test.c"
FIND_QUERY="$FIND_QUERY -and -not -name cracker.c" FIND_QUERY="$FIND_QUERY -and -not -name cracker.c"
FIND_QUERY="$FIND_QUERY -and -not -name version_test.c" FIND_QUERY="$FIND_QUERY -and -not -name version_test.c"
FIND_QUERY="$FIND_QUERY -and -not -name '*_fuzz_test.cc'"
FIND_QUERY="$FIND_QUERY -and -not -wholename './testing/fuzzing/*'" FIND_QUERY="$FIND_QUERY -and -not -wholename './testing/fuzzing/*'"
if [ "$SKIP_GTEST" == 1 ]; then if [ "$SKIP_GTEST" == 1 ]; then

View File

@ -1 +1 @@
591106a972c27f19e72bd8927964e1ecc57976f4f4ff538699eaf3eb6236f9ea /usr/local/bin/tox-bootstrapd c93318d8f05a4e9c9bd74bfb6f01b776c7dcb7450745dfe5f31dac592353cd74 /usr/local/bin/tox-bootstrapd

View File

@ -1,5 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
package(features = ["-layering_check"])
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["websockify.go"], srcs = ["websockify.go"],

View File

@ -0,0 +1,25 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
cc_library(
name = "fuzz_adapter",
srcs = ["fuzz_adapter.c"],
hdrs = ["fuzz_adapter.h"],
visibility = ["//c-toxcore:__subpackages__"],
)
cc_fuzz_test(
name = "bootstrap_fuzzer",
srcs = ["bootstrap_harness.cc"],
copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:bootstrap_fuzzer"],
deps = ["//c-toxcore/toxcore:tox"],
)
cc_fuzz_test(
name = "toxsave_fuzz_test",
srcs = ["toxsave_harness.cc"],
copts = ["-UNDEBUG"],
corpus = ["//tools/toktok-fuzzer/corpus:toxsave_fuzzer"],
deps = ["//c-toxcore/toxcore:tox"],
)

View File

@ -4,12 +4,13 @@
#include "../../toxcore/tox.h" #include "../../toxcore/tox.h"
#include "fuzz_adapter.h" #include "fuzz_adapter.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
network_adapter_init(data, size); network_adapter_init(data, size);
Tox_Err_New error_new; Tox_Err_New error_new;
Tox *tox = tox_new(NULL, &error_new); Tox *tox = tox_new(nullptr, &error_new);
assert(tox != nullptr); assert(tox != nullptr);
assert(error_new == TOX_ERR_NEW_OK); assert(error_new == TOX_ERR_NEW_OK);

View File

@ -66,7 +66,7 @@ ssize_t fuzz_recvfrom(int sockfd, void *buf, size_t len,
src_addr->sa_family = AF_INET; src_addr->sa_family = AF_INET;
// We want an AF_INET address with dummy values // We want an AF_INET address with dummy values
struct sockaddr_in *addr_in = (struct sockaddr_in *) src_addr; struct sockaddr_in *addr_in = (struct sockaddr_in *)(void *)src_addr;
addr_in->sin_port = 12356; addr_in->sin_port = 12356;
addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1; addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1;
*addr_len = sizeof(struct sockaddr); *addr_len = sizeof(struct sockaddr);

View File

@ -2,6 +2,7 @@
#include "../../toxcore/tox.h" #include "../../toxcore/tox.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
Tox_Err_Options_New error_options; Tox_Err_Options_New error_options;

View File

@ -1,4 +1,5 @@
load("@rules_cc//cc:defs.bzl", "cc_test") load("@rules_cc//cc:defs.bzl", "cc_test")
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
load("//tools:no_undefined.bzl", "cc_library") load("//tools:no_undefined.bzl", "cc_library")
package(features = ["layering_check"]) package(features = ["layering_check"])
@ -51,6 +52,7 @@ cc_library(
visibility = ["//c-toxcore:__subpackages__"], visibility = ["//c-toxcore:__subpackages__"],
deps = [ deps = [
":ccompat", ":ccompat",
"//c-toxcore/testing/fuzzing:fuzz_adapter",
"@libsodium", "@libsodium",
], ],
) )
@ -121,6 +123,7 @@ cc_library(
], ],
deps = [ deps = [
":ccompat", ":ccompat",
"//c-toxcore/testing/fuzzing:fuzz_adapter",
"@pthread", "@pthread",
], ],
) )
@ -169,6 +172,7 @@ cc_library(
":logger", ":logger",
":mono_time", ":mono_time",
":util", ":util",
"//c-toxcore/testing/fuzzing:fuzz_adapter",
"@libsodium", "@libsodium",
"@psocket", "@psocket",
"@pthread", "@pthread",
@ -279,6 +283,13 @@ cc_test(
], ],
) )
cc_fuzz_test(
name = "DHT_fuzz_test",
srcs = ["DHT_fuzz_test.cc"],
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
deps = [":DHT"],
)
cc_library( cc_library(
name = "onion", name = "onion",
srcs = ["onion.c"], srcs = ["onion.c"],
@ -561,6 +572,25 @@ cc_library(
], ],
) )
cc_test(
name = "tox_events_test",
size = "small",
srcs = ["tox_events_test.cc"],
deps = [
":crypto_core",
":tox_events",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)
cc_fuzz_test(
name = "tox_events_fuzz_test",
srcs = ["tox_events_fuzz_test.cc"],
corpus = ["//tools/toktok-fuzzer/corpus:tox_events_fuzz_test"],
deps = [":tox_events"],
)
cc_library( cc_library(
name = "tox_dispatch", name = "tox_dispatch",
srcs = ["tox_dispatch.c"], srcs = ["tox_dispatch.c"],

80
toxcore/DHT_fuzz_test.cc Normal file
View File

@ -0,0 +1,80 @@
#include "DHT.h"
#include <cstdlib>
#include <vector>
namespace {
void TestHandleRequest(const uint8_t *input_data, size_t input_size)
{
const uint8_t *data = input_data;
size_t size = input_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 request[MAX_CRYPTO_REQUEST_SIZE];
uint8_t request_id;
handle_request(self_public_key, self_secret_key, public_key, request, &request_id, data, size);
}
void TestUnpackNodes(const uint8_t *input_data, size_t input_size)
{
const uint8_t *data = input_data;
size_t size = input_size;
if (size < 1) {
return;
}
const bool tcp_enabled = data[0];
++data;
--size;
Node_format nodes[5];
uint16_t processed_data_len;
const int packed_count = unpack_nodes(nodes, 5, &processed_data_len, data, size, tcp_enabled);
if (packed_count > 0) {
Logger *logger = logger_new();
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
const int packed_size
= pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count);
LOGGER_ASSERT(logger, packed_size == processed_data_len,
"packed size (%d) != unpacked size (%d)", packed_size, processed_data_len);
logger_kill(logger);
}
}
} // namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *input_data, size_t input_size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *input_data, size_t input_size)
{
const uint8_t *data = input_data;
size_t size = input_size;
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;
}
}

View File

@ -13,6 +13,10 @@
#include "attributes.h" #include "attributes.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MIN_LOGGER_LEVEL #ifndef MIN_LOGGER_LEVEL
#define MIN_LOGGER_LEVEL LOGGER_LEVEL_INFO #define MIN_LOGGER_LEVEL LOGGER_LEVEL_INFO
#endif #endif
@ -93,4 +97,8 @@ void logger_write(
} \ } \
} while (0) } while (0)
#ifdef __cplusplus
} // extern "C"
#endif
#endif // C_TOXCORE_TOXCORE_LOGGER_H #endif // C_TOXCORE_TOXCORE_LOGGER_H

View File

@ -127,10 +127,12 @@ static bool should_ignore_recv_error(int err)
return err == EWOULDBLOCK; return err == EWOULDBLOCK;
} }
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
static bool should_ignore_connect_error(int err) static bool should_ignore_connect_error(int err)
{ {
return err == EWOULDBLOCK || err == EINPROGRESS; return err == EWOULDBLOCK || err == EINPROGRESS;
} }
#endif
non_null() non_null()
static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize) static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize)
@ -276,6 +278,7 @@ static int make_socktype(int type)
} }
#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || !defined(NDEBUG)
static int make_family(Family tox_family) static int make_family(Family tox_family)
{ {
switch (tox_family.value) { switch (tox_family.value) {
@ -292,6 +295,7 @@ static int make_family(Family tox_family)
return tox_family.value; return tox_family.value;
} }
} }
#endif // !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(NDEBUG)
static const Family *make_tox_family(int family) static const Family *make_tox_family(int family)
{ {
@ -1033,7 +1037,7 @@ Networking_Core *new_networking_ex(const Logger *log, const IP *ip, uint16_t por
for (uint16_t tries = port_from; tries <= port_to; ++tries) { for (uint16_t tries = port_from; tries <= port_to; ++tries) {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
int res = 0; int res = addrsize > 0 ? 0 : -1;
#else #else
int res = bind(temp->sock.sock, (struct sockaddr *)&addr, addrsize); int res = bind(temp->sock.sock, (struct sockaddr *)&addr, addrsize);
#endif #endif
@ -1459,7 +1463,7 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port)
} }
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return true; return addrsize != 0;
#else #else
LOGGER_DEBUG(log, "connecting socket %d to %s:%d", LOGGER_DEBUG(log, "connecting socket %d to %s:%d",
(int)sock.sock, ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port->port)); (int)sock.sock, ip_ntoa(&ip_port->ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port->port));
@ -1610,7 +1614,7 @@ bool bind_to_port(Socket sock, Family family, uint16_t port)
} }
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return true; return addrsize != 0;
#else #else
return bind(sock.sock, (struct sockaddr *)&addr, addrsize) == 0; return bind(sock.sock, (struct sockaddr *)&addr, addrsize) == 0;
#endif #endif

View File

@ -246,9 +246,9 @@ void tox_events_get_bytes(const Tox_Events *events, uint8_t *bytes)
Tox_Events *tox_events_load(const uint8_t *bytes, uint32_t bytes_size) Tox_Events *tox_events_load(const uint8_t *bytes, uint32_t bytes_size)
{ {
msgpack_unpacked msg; msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
size_t offset = 0; size_t offset = 0;
msgpack_unpacked_init(&msg);
const msgpack_unpack_return result = msgpack_unpack_next(&msg, (const char *)bytes, bytes_size, &offset); const msgpack_unpack_return result = msgpack_unpack_next(&msg, (const char *)bytes, bytes_size, &offset);
if (result != MSGPACK_UNPACK_SUCCESS) { if (result != MSGPACK_UNPACK_SUCCESS) {

View File

@ -0,0 +1,14 @@
#include "tox_events.h"
namespace {
void TestUnpack(const uint8_t *data, size_t size) { tox_events_free(tox_events_load(data, size)); }
} // namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
TestUnpack(data, size);
return 0;
}

View File

@ -0,0 +1,44 @@
#include "tox_events.h"
#include <gtest/gtest.h>
#include <array>
#include <vector>
#include "crypto_core.h"
namespace {
TEST(ToxEvents, UnpackRandomDataDoesntCrash)
{
std::array<uint8_t, 128> data;
random_bytes(data.data(), data.size());
tox_events_free(tox_events_load(data.data(), data.size()));
}
TEST(ToxEvents, UnpackEmptyDataFails)
{
std::array<uint8_t, 1> data;
Tox_Events *events = tox_events_load(data.end(), 0);
EXPECT_EQ(events, nullptr);
}
TEST(ToxEvents, UnpackEmptyArrayCreatesEmptyEvents)
{
std::array<uint8_t, 1> data{0x90}; // empty msgpack array
Tox_Events *events = tox_events_load(data.data(), data.size());
ASSERT_NE(events, nullptr);
EXPECT_EQ(tox_events_get_conference_connected_size(events), 0);
tox_events_free(events);
}
// TODO(iphydf): Enable this test once we've fully moved away from msgpack-c.
#if 0
TEST(ToxEvents, DealsWithHugeMsgpackArrays)
{
std::vector<uint8_t> data{0xdd, 0xff, 0xff, 0xff, 0xff};
EXPECT_EQ(tox_events_load(data.data(), data.size()), nullptr);
}
#endif
} // namespace