[libc-commits] [libc] a4f45ee - [libc] Lay out framework for fuzzing libc functions.
Paula Toth via libc-commits
libc-commits at lists.llvm.org
Fri Feb 21 19:21:22 PST 2020
Author: Paula Toth
Date: 2020-02-21T19:15:46-08:00
New Revision: a4f45ee73a9e948622488f874d5e01408dffba2a
URL: https://github.com/llvm/llvm-project/commit/a4f45ee73a9e948622488f874d5e01408dffba2a
DIFF: https://github.com/llvm/llvm-project/commit/a4f45ee73a9e948622488f874d5e01408dffba2a.diff
LOG: [libc] Lay out framework for fuzzing libc functions.
Summary:
Added fuzzing test for strcpy and some documentation related to fuzzing.
This will be the first step in integrating this with oss-fuzz.
Reviewers: sivachandra, abrachet
Reviewed By: sivachandra, abrachet
Subscribers: gchatelet, abrachet, mgorny, MaskRay, tschuett, libc-commits
Tags: #libc-project
Differential Revision: https://reviews.llvm.org/D74091
Added:
libc/docs/fuzzing.rst
libc/fuzzing/CMakeLists.txt
libc/fuzzing/string/CMakeLists.txt
libc/fuzzing/string/strcpy_fuzz.cpp
Modified:
libc/CMakeLists.txt
libc/cmake/modules/LLVMLibCRules.cmake
libc/docs/source_layout.rst
Removed:
################################################################################
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index a4c95eec9c05..fd750a06e0e1 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -32,3 +32,4 @@ add_subdirectory(utils)
# of the other directories.
add_subdirectory(lib)
add_subdirectory(test)
+add_subdirectory(fuzzing)
diff --git a/libc/cmake/modules/LLVMLibCRules.cmake b/libc/cmake/modules/LLVMLibCRules.cmake
index f5bf3f8a0992..ae4a1448a594 100644
--- a/libc/cmake/modules/LLVMLibCRules.cmake
+++ b/libc/cmake/modules/LLVMLibCRules.cmake
@@ -300,7 +300,7 @@ function(add_libc_unittest target_name)
if(NOT LLVM_INCLUDE_TESTS)
return()
endif()
-
+
cmake_parse_arguments(
"LIBC_UNITTEST"
"" # No optional arguments
@@ -375,6 +375,71 @@ function(add_libc_testsuite suite_name)
add_dependencies(check-libc ${suite_name})
endfunction(add_libc_testsuite)
+# Rule to add a fuzzer test.
+# Usage
+# add_libc_fuzzer(
+# <target name>
+# SRCS <list of .cpp files for the test>
+# HDRS <list of .h files for the test>
+# DEPENDS <list of dependencies>
+# )
+function(add_libc_fuzzer target_name)
+ cmake_parse_arguments(
+ "LIBC_FUZZER"
+ "" # No optional arguments
+ "" # Single value arguments
+ "SRCS;HDRS;DEPENDS" # Multi-value arguments
+ ${ARGN}
+ )
+ if(NOT LIBC_FUZZER_SRCS)
+ message(FATAL_ERROR "'add_libc_fuzzer' target requires a SRCS list of .cpp files.")
+ endif()
+ if(NOT LIBC_FUZZER_DEPENDS)
+ message(FATAL_ERROR "'add_libc_fuzzer' target requires a DEPENDS list of 'add_entrypoint_object' targets.")
+ endif()
+
+ set(library_deps "")
+ foreach(dep IN LISTS LIBC_FUZZER_DEPENDS)
+ get_target_property(dep_type ${dep} "TARGET_TYPE")
+ if (dep_type)
+ string(COMPARE EQUAL ${dep_type} ${ENTRYPOINT_OBJ_TARGET_TYPE} dep_is_entrypoint)
+ if(dep_is_entrypoint)
+ get_target_property(obj_file ${dep} "OBJECT_FILE_RAW")
+ list(APPEND library_deps ${obj_file})
+ continue()
+ endif()
+ endif()
+ # TODO: Check if the dep is a normal CMake library target. If yes, then add it
+ # to the list of library_deps.
+ endforeach(dep)
+
+ add_executable(
+ ${target_name}
+ EXCLUDE_FROM_ALL
+ ${LIBC_FUZZER_SRCS}
+ ${LIBC_FUZZER_HDRS}
+ )
+ target_include_directories(
+ ${target_name}
+ PRIVATE
+ ${LIBC_SOURCE_DIR}
+ ${LIBC_BUILD_DIR}
+ ${LIBC_BUILD_DIR}/include
+ )
+
+ if(library_deps)
+ target_link_libraries(${target_name} PRIVATE ${library_deps})
+ endif()
+
+ set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+
+ add_dependencies(
+ ${target_name}
+ ${LIBC_FUZZER_DEPENDS}
+ )
+ add_dependencies(libc-fuzzer ${target_name})
+endfunction(add_libc_fuzzer)
+
# Rule to add header only libraries.
# Usage
# add_header_library(
diff --git a/libc/docs/fuzzing.rst b/libc/docs/fuzzing.rst
new file mode 100644
index 000000000000..a16cac6f1a55
--- /dev/null
+++ b/libc/docs/fuzzing.rst
@@ -0,0 +1,15 @@
+Fuzzing for LLVM-libc
+---------------------
+
+Fuzzing tests are used to ensure quality and security of LLVM-libc
+implementations.
+
+Each fuzzing test lives under the fuzzing directory in a subdirectory
+corresponding with the src layout.
+
+Currently we use system libc for functions that have yet to be implemented,
+however as they are implemented the fuzzers will be changed to use our
+implementation to increase coverage for testing.
+
+Fuzzers will be run on `oss-fuzz <https://github.com/google/oss-fuzz>`_ and the
+check-libc target will ensure that they build correctly.
diff --git a/libc/docs/source_layout.rst b/libc/docs/source_layout.rst
index 685798c19575..9bf63521bf07 100644
--- a/libc/docs/source_layout.rst
+++ b/libc/docs/source_layout.rst
@@ -7,6 +7,7 @@ directories::
+ libc
- cmake
- docs
+ - fuzzing
- include
- lib
- loader
@@ -31,6 +32,13 @@ The ``docs`` directory
The ``docs`` directory contains design docs and also informative documents like
this document on source layout.
+The ``fuzzing`` directory
+----------------------
+
+This directory contains fuzzing tests for the various components of llvm-libc. The
+directory structure within this directory mirrors the directory structure of the
+top-level ``libc`` directory itself. For more details, see :doc:`fuzzing`.
+
The ``include`` directory
-------------------------
@@ -62,7 +70,7 @@ The ``src`` directory
This directory contains the implementations of the llvm-libc entrypoints. It is
further organized as follows:
-1. There is a toplevel CMakeLists.txt file.
+1. There is a top-level CMakeLists.txt file.
2. For every public header file provided by llvm-libc, there exists a
corresponding directory in the ``src`` directory. The name of the directory
is same as the base name of the header file. For example, the directory
diff --git a/libc/fuzzing/CMakeLists.txt b/libc/fuzzing/CMakeLists.txt
new file mode 100644
index 000000000000..1b950ad9b721
--- /dev/null
+++ b/libc/fuzzing/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
+add_custom_target(libc-fuzzer)
+add_dependencies(check-libc libc-fuzzer)
+
+add_subdirectory(string)
diff --git a/libc/fuzzing/string/CMakeLists.txt b/libc/fuzzing/string/CMakeLists.txt
new file mode 100644
index 000000000000..0482b961e576
--- /dev/null
+++ b/libc/fuzzing/string/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_libc_fuzzer(
+ strcpy_fuzz
+ SRCS
+ strcpy_fuzz.cpp
+ DEPENDS
+ strcpy
+)
diff --git a/libc/fuzzing/string/strcpy_fuzz.cpp b/libc/fuzzing/string/strcpy_fuzz.cpp
new file mode 100644
index 000000000000..51a85d6be0a6
--- /dev/null
+++ b/libc/fuzzing/string/strcpy_fuzz.cpp
@@ -0,0 +1,38 @@
+//===--------------------- strcpy_fuzz.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Fuzzing test for llvm-libc strcpy implementation.
+///
+//===----------------------------------------------------------------------===//
+#include "src/string/strcpy.h"
+#include <stdint.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ // Validate input
+ if (!size) return 0;
+ if (data[size - 1] != '\0') return 0;
+ const char *src = (const char *)data;
+
+ char *dest = new char[size];
+ if (!dest) __builtin_trap();
+
+ __llvm_libc::strcpy(dest, src);
+
+ size_t i;
+ for (i = 0; src[i] != '\0'; i++) {
+ // Ensure correctness of strcpy
+ if (dest[i] != src[i]) __builtin_trap();
+ }
+ // Ensure strcpy null terminates dest
+ if (dest[i] != src[i]) __builtin_trap();
+
+ delete[] dest;
+
+ return 0;
+}
+
More information about the libc-commits
mailing list