Skip to content

Commit

Permalink
test: Add fuzz tests to the coverage run.
Browse files Browse the repository at this point in the history
So we don't need to write so many edge case tests ourselves for things
like parsers, which really don't need those manual tests, as long as we
can check for some properties like "can output the parsed data and it'll
be the same as the input".
  • Loading branch information
iphydf committed Jan 12, 2024
1 parent df76f5c commit 50f1b30
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 64 deletions.
43 changes: 21 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,21 +160,7 @@ if(BOOTSTRAP_DAEMON AND WIN32)
set(BOOTSTRAP_DAEMON OFF)
endif()

# Enabling this breaks all other tests and no network connections will be possible
option(BUILD_FUZZ_TESTS "Build fuzzing harnesses" OFF)
if(BUILD_FUZZ_TESTS)
message(STATUS "Building in fuzz testing mode, no network connection will be possible")
# Disable everything we can
set(AUTOTEST OFF)
set(BUILD_MISC_TESTS OFF)
set(BUILD_FUN_UTILS OFF)
set(ENABLE_SHARED OFF)
set(MUST_BUILD_TOXAV OFF)
set(BUILD_TOXAV OFF)
set(BOOTSTRAP_DAEMON OFF)
set(DHT_BOOTSTRAP OFF)
endif()


if(MSVC)
option(MSVC_STATIC_SODIUM "Whether to link libsodium statically for MSVC" OFF)
Expand Down Expand Up @@ -448,20 +434,33 @@ endif()
################################################################################

# Create combined library from all the sources.
add_module(toxcore ${toxcore_SOURCES})
if(ENABLE_SHARED)
add_library(toxcore_shared SHARED ${toxcore_SOURCES})
set_target_properties(toxcore_shared PROPERTIES OUTPUT_NAME toxcore)
target_link_libraries(toxcore_shared PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_shared PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_shared SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_shared PRIVATE ${toxcore_COMPILE_OPTIONS})
endif()

# Link it to all dependencies.
if(TARGET toxcore_static)
if(ENABLE_STATIC)
add_library(toxcore_static STATIC ${toxcore_SOURCES})
if(NOT MSVC)
set_target_properties(toxcore_static PROPERTIES OUTPUT_NAME toxcore)
endif()
target_link_libraries(toxcore_static PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_static PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_static SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_static PRIVATE ${toxcore_COMPILE_OPTIONS})
endif()
if(TARGET toxcore_shared)
target_link_libraries(toxcore_shared PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_shared PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_shared SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_shared PRIVATE ${toxcore_COMPILE_OPTIONS})

if(BUILD_FUZZ_TESTS)
add_library(toxcore_fuzz STATIC ${toxcore_SOURCES})
target_link_libraries(toxcore_fuzz PRIVATE ${toxcore_LINK_LIBRARIES})
target_link_directories(toxcore_fuzz PUBLIC ${toxcore_LINK_DIRECTORIES})
target_include_directories(toxcore_fuzz SYSTEM PRIVATE ${toxcore_INCLUDE_DIRECTORIES})
target_compile_options(toxcore_fuzz PRIVATE ${toxcore_COMPILE_OPTIONS})
target_compile_definitions(toxcore_fuzz PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")
endif()

# Make version script (on systems that support it) to limit symbol visibility.
Expand Down
13 changes: 0 additions & 13 deletions cmake/ModulePackage.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,6 @@ if(FULLY_STATIC)
set(ENABLE_STATIC ON)
endif()

function(add_module lib)
if(ENABLE_SHARED)
add_library(${lib}_shared SHARED ${ARGN})
set_target_properties(${lib}_shared PROPERTIES OUTPUT_NAME ${lib})
endif()
if(ENABLE_STATIC)
add_library(${lib}_static STATIC ${ARGN})
if(NOT MSVC)
set_target_properties(${lib}_static PROPERTIES OUTPUT_NAME ${lib})
endif()
endif()
endfunction()

function(install_module lib)
if(TARGET ${lib}_shared)
set_target_properties(${lib}_shared PROPERTIES
Expand Down
4 changes: 2 additions & 2 deletions other/analysis/check_includes
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ out = (subprocess.run(

errors = 0
for line in out.split("\n"):
# other/fun can do what it wants.
if "/fun/" in line:
# other/fun and mallocfail can do what they want.
if "/fun/" in line or "/mallocfail/" in line:
continue
filename, include = line.split(":", 1)
# We only check headers.
Expand Down
1 change: 1 addition & 0 deletions other/docker/coverage/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ RUN source .github/scripts/flags-coverage.sh \
-DSTRICT_ABI=ON \
-DAUTOTEST=ON \
-DPROXY_TEST=ON \
-DBUILD_FUZZ_TESTS=ON \
-DUSE_IPV6=OFF \
-DTEST_TIMEOUT_SECONDS=40 \
&& cmake --build _build --parallel 8 --target install
Expand Down
29 changes: 18 additions & 11 deletions testing/fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
# For coverage tests
target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION")

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

set(LIBFUZZER_LINKER_FLAGS)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(LIBFUZZER_LINKER_FLAGS "-fsanitize=fuzzer")
else()
message(SEND_ERROR "Compiler must be Clang to build fuzz targets")
endif()

function(fuzz_test target source_dir)
set(${target}_CORPUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/toktok-fuzzer/corpus/${target}_fuzz_test)
file(GLOB ${target}_fuzz_CORPUS "${${target}_CORPUS_DIR}/*")
add_executable(${target}_fuzz_test ${source_dir}/${target}_fuzz_test.cc)
target_link_libraries(${target}_fuzz_test PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})
if(${target}_fuzz_CORPUS)
add_test(NAME ${target}_fuzz COMMAND ${CROSSCOMPILING_EMULATOR} ${target}_fuzz_test -max_total_time=10 ${${target}_fuzz_CORPUS})
endif()
endfunction()

# Fuzzes the toxsave API
add_executable(toxsave_fuzzer toxsave_harness.cc)
target_link_libraries(toxsave_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
target_link_libraries(toxsave_fuzzer PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})

# Fuzzes the bootstrap process
add_executable(bootstrap_fuzzer bootstrap_harness.cc)
target_link_libraries(bootstrap_fuzzer PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})

add_executable(DHT_fuzz_test ../../toxcore/DHT_fuzz_test.cc)
target_link_libraries(DHT_fuzz_test PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
target_link_libraries(bootstrap_fuzzer PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS})

add_executable(tox_events_fuzz_test ../../toxcore/tox_events_fuzz_test.cc)
target_link_libraries(tox_events_fuzz_test PRIVATE toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS})
fuzz_test(DHT ../../toxcore)
fuzz_test(forwarding ../../toxcore)
fuzz_test(group_announce ../../toxcore)
fuzz_test(group_moderation ../../toxcore)
fuzz_test(tox_events ../../toxcore)
22 changes: 15 additions & 7 deletions testing/fuzzing/fuzz_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <memory>
#include <unordered_map>
Expand All @@ -28,13 +29,20 @@ struct Fuzz_Data {
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;
}
struct Consumer {
Fuzz_Data &fd;

template <typename T>
operator T()
{
const uint8_t *bytes = fd.consume(sizeof(T));
T val;
std::memcpy(&val, bytes, sizeof(T));
return val;
}
};

Consumer consume1() { return Consumer{*this}; }

const uint8_t *consume(std::size_t count)
{
Expand Down
1 change: 1 addition & 0 deletions toxcore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ cc_test(
srcs = ["util_test.cc"],
deps = [
":crypto_core",
":crypto_core_test_util",
":util",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
Expand Down
13 changes: 8 additions & 5 deletions toxcore/group_announce_fuzz_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ namespace {
void TestUnpackAnnouncesList(Fuzz_Data &input)
{
CONSUME1_OR_RETURN(const uint8_t max_count, input);
std::vector<GC_Announce> announces(max_count);
// Always allocate at least something to avoid passing nullptr to functions below.
std::vector<GC_Announce> announces(max_count + 1);

Check warning on line 16 in toxcore/group_announce_fuzz_test.cc

View check run for this annotation

Codecov / codecov/patch

toxcore/group_announce_fuzz_test.cc#L16

Added line #L16 was not covered by tests

// TODO(iphydf): How do we know the packed size?
CONSUME1_OR_RETURN(const uint16_t packed_size, input);

Logger *logger = logger_new();
if (gca_unpack_announces_list(logger, input.data, input.size, announces.data(), max_count)
!= -1) {
std::vector<uint8_t> packed(packed_size);
// Always allocate at least something to avoid passing nullptr to functions below.
std::vector<uint8_t> packed(packed_size + 1);

Check warning on line 25 in toxcore/group_announce_fuzz_test.cc

View check run for this annotation

Codecov / codecov/patch

toxcore/group_announce_fuzz_test.cc#L25

Added line #L25 was not covered by tests
size_t processed;
gca_pack_announces_list(
logger, packed.data(), packed.size(), announces.data(), announces.size(), &processed);
logger, packed.data(), packed_size, announces.data(), max_count, &processed);

Check warning on line 28 in toxcore/group_announce_fuzz_test.cc

View check run for this annotation

Codecov / codecov/patch

toxcore/group_announce_fuzz_test.cc#L28

Added line #L28 was not covered by tests
}
logger_kill(logger);
}
Expand All @@ -37,8 +39,9 @@ void TestUnpackPublicAnnounce(Fuzz_Data &input)

Logger *logger = logger_new();
if (gca_unpack_public_announce(logger, input.data, input.size, &public_announce) != -1) {
std::vector<uint8_t> packed(packed_size);
gca_pack_public_announce(logger, packed.data(), packed.size(), &public_announce);
// Always allocate at least something to avoid passing nullptr to functions below.
std::vector<uint8_t> packed(packed_size + 1);
gca_pack_public_announce(logger, packed.data(), packed_size, &public_announce);

Check warning on line 44 in toxcore/group_announce_fuzz_test.cc

View check run for this annotation

Codecov / codecov/patch

toxcore/group_announce_fuzz_test.cc#L43-L44

Added lines #L43 - L44 were not covered by tests
}
logger_kill(logger);
}
Expand Down
7 changes: 3 additions & 4 deletions toxcore/util_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
#include <gtest/gtest.h>

#include "crypto_core.h"
#include "crypto_core_test_util.hh"

namespace {

TEST(Util, TwoRandomIdsAreNotEqual)
{
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
Test_Random rng;
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE];
Expand All @@ -23,8 +23,7 @@ TEST(Util, TwoRandomIdsAreNotEqual)

TEST(Util, IdCopyMakesKeysEqual)
{
const Random *rng = system_random();
ASSERT_NE(rng, nullptr);
Test_Random rng;
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE] = {0};
Expand Down

0 comments on commit 50f1b30

Please sign in to comment.