commit 78cf7a7b194e6cc517614cd52b19048398ef655d from: Sergey Bronnikov via: Sergey Bronnikov date: Tue Jul 04 15:31:33 2023 UTC Initial commit Patch includes a CMake infrustructure and a test for a strptime(3) function. BSD implementation of this function could be buggy, see [1]. 1. https://github.com/tarantool/tarantool/issues/8525 commit - /dev/null commit + 78cf7a7b194e6cc517614cd52b19048398ef655d blob - /dev/null blob + 46e85f75ea7f7425395f19b1083060c05f036950 (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1,3 @@ +build +.ccls-cache +crash-* blob - /dev/null blob + b9f0ed8b598a692286c51c667a4f7789a2c9ca83 (mode 644) --- /dev/null +++ CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.10.2) + +project(libc-tests + DESCRIPTION "Fuzzing libc" + LANGUAGES C CXX + VERSION "1.0.0" +) + +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") + +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR + NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR + "\n" + "Building is supported with Clang compiler only.\n" + " $ rm -rf build\n" + " $ cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -S . -B build\n" + " $ cmake --build build --parallel\n" + "\n") +endif() + +enable_testing() +add_subdirectory(tests) blob - /dev/null blob + ba6be8c10afc083c5b067d6db8632d733c695c6a (mode 644) --- /dev/null +++ CMakePresets.json @@ -0,0 +1,59 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "displayName": "Default Config (Unix Makefile)", + "description": "Default build using Unix Makefile generator", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++", + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "BOOL", + "value": "ON" + } + } + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default", + "jobs": 10 + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "output": {"outputOnFailure": true}, + "execution": {"noTestsAction": "error", "stopOnFailure": true} + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + } + ] + } + ] +} blob - /dev/null blob + d2da6a20a19cfaac69323cfa0b291e751b8a1455 (mode 644) --- /dev/null +++ LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023 Sergey Bronnikov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. blob - /dev/null blob + 7396966529584e30e59b60b465e191f8e689c18a (mode 644) --- /dev/null +++ README.md @@ -0,0 +1,29 @@ +## Fuzzing libc + +is a set of fuzzing tests intended for testing standard C library. +By default system C library is used. + +### Building + +```sh +git clone --jobs $(nproc) --recursive https://github.com/ligurio/libc-tests +CC=clang CXX=clang++ cmake -S . -B build +cmake --build build --parallel +``` + +or + +``` +$ cmake --workflow --preset default +``` + +### Running + +```sh +cmake --build build --target test +cd build && ctest -R strptime_test --verbose +``` + +### License + +MIT License, [Sergey Bronnikov](https://bronevichok.ru/) blob - /dev/null blob + 3139149b680de48abb641abc25bef247679b78be (mode 644) --- /dev/null +++ tests/CMakeLists.txt @@ -0,0 +1,74 @@ +add_library(fuzzer_config INTERFACE) + +target_compile_options( + fuzzer_config + INTERFACE + $<$>: + -fsanitize=fuzzer + > + $<$: + ${CXX} + ${CXXFLAGS} + > +) +target_link_libraries( + fuzzer_config + INTERFACE + $<$>: + -fsanitize=fuzzer + > + $<$: + $ENV{LIB_FUZZING_ENGINE} + > +) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LDFLAGS "${LDFLAGS} ${CMAKE_C_FLAGS_DEBUG}") +endif (CMAKE_BUILD_TYPE STREQUAL "Debug") + +set(FUZZ_TEST_TARGETS "") + +include(CheckFunctionExists) + +function(create_test) + cmake_parse_arguments( + FUZZ + "" + "FILENAME" + "SOURCES;LIBRARIES" + ${ARGN} + ) + + check_function_exists(${FUZZ_FILENAME} HAVE_${FUZZ_FILENAME}) + if (NOT ${HAVE_${FUZZ_FILENAME}}) + message(WARNING "Function ${FUZZ_FILENAME} is missed") + return() + endif () + + get_filename_component(test_name ${FUZZ_FILENAME} NAME_WE) + add_executable(${test_name} ${FUZZ_SOURCES}) + + target_link_libraries(${test_name} PUBLIC fuzzer_config ${FUZZ_LIBRARIES} ${LDFLAGS}) + target_compile_options(${test_name} PRIVATE -Wall -Wextra -Wpedantic -Wno-unused-parameter -g) + string(REPLACE "_test" "" test_prefix ${test_name}) + add_test(NAME ${test_name} + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${test_name} + -use_value_profile=1 + -report_slow_units=5 + -reload=1 + -reduce_inputs=1 + -print_pcs=1 + -print_final_stats=1 + -mutate_depth=20 + -runs=5 + -artifact_prefix=${test_name}_ + ) +endfunction() + +file(GLOB tests LIST_DIRECTORIES false ${CMAKE_CURRENT_SOURCE_DIR} *.c *.cc) +foreach(filename ${tests}) + get_filename_component(test_name ${filename} NAME_WE) + create_test(FILENAME ${test_name} + SOURCES ${filename} + LIBRARIES "") +endforeach() blob - /dev/null blob + 6de8978d644f94501eddaec87e6d66bf8a1241a9 (mode 644) --- /dev/null +++ tests/strptime_test.cc @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#include + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + + auto buf = fdp.ConsumeRandomLengthString(); + auto fmt = fdp.ConsumeRandomLengthString(); + + struct tm tm = {}; + char *res = strptime(buf.c_str(), fmt.c_str(), &tm); + if (!res) + return 0; + + assert(tm.tm_sec >= 0 && tm.tm_sec <= 60); + assert(tm.tm_min >= 0 && tm.tm_min <= 59); + assert(tm.tm_hour >= 0 && tm.tm_hour <= 23); + assert(tm.tm_mday >= 0 && tm.tm_mday <= 28); + assert(tm.tm_mon >= 0 && tm.tm_mon <= 11); + assert(tm.tm_year >= 0); + assert(tm.tm_wday >= 0 && tm.tm_wday <= 6); + assert(tm.tm_yday >= 0 && tm.tm_yday <= 365); + assert(tm.tm_isdst >= 0); + + return 0; +}