Commit Diff


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
+        $<$<NOT:$<BOOL:${OSS_FUZZ}>>:
+        -fsanitize=fuzzer
+        >
+        $<$<BOOL:${OSS_FUZZ}>:
+        ${CXX}
+        ${CXXFLAGS}
+        >
+)
+target_link_libraries(
+    fuzzer_config
+    INTERFACE
+        $<$<NOT:$<BOOL:${OSS_FUZZ}>>:
+        -fsanitize=fuzzer
+        >
+        $<$<BOOL:${OSS_FUZZ}>:
+        $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 <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+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;
+}