Skip to content

Commit

Permalink
Add Makefile target and harness to fuzz with libFuzzer
Browse files Browse the repository at this point in the history
This can be run locally with `make libFuzzer` but the harness will be
integrated into oss-fuzz for large-scale fuzzing.
  • Loading branch information
philipturnbull committed Jun 27, 2017
1 parent 70a6a16 commit c1dea4e
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_
option(CMARK_TESTS "Build cmark tests and enable testing" ON)
option(CMARK_STATIC "Build static libcmark library" ON)
option(CMARK_SHARED "Build shared libcmark library" ON)
option(CMARK_LIB_FUZZER "Build libFuzzer fuzzing harness" OFF)

add_subdirectory(src)
if(CMARK_TESTS AND CMARK_SHARED)
Expand Down
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ BENCHFILE=$(BENCHDIR)/benchinput.md
ALLTESTS=alltests.md
NUMRUNS?=10
CMARK=$(BUILDDIR)/src/cmark
CMARK_FUZZ=$(BUILDDIR)/src/cmark-fuzz
PROG?=$(CMARK)
VERSION?=$(SPECVERSION)
RELEASE?=CommonMark-$(VERSION)
Expand Down Expand Up @@ -81,6 +82,13 @@ afl:
-t 100 \
$(CMARK) $(CMARK_OPTS)

libFuzzer:
@[ -n "$(LIB_FUZZER_PATH)" ] || { echo '$$LIB_FUZZER_PATH not set'; false; }
mkdir -p $(BUILDDIR)
cd $(BUILDDIR) && cmake -DCMAKE_BUILD_TYPE=Asan -DCMARK_LIB_FUZZER=ON -DCMAKE_LIB_FUZZER_PATH=$(LIB_FUZZER_PATH) ..
$(MAKE) -j2 -C $(BUILDDIR) cmark-fuzz
test/run-cmark-fuzz $(CMARK_FUZZ)

clang-check: all
${CLANG_CHECK} -p build -analyze src/*.c

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ To do a more systematic fuzz test with [american fuzzy lop]:

AFL_PATH=/path/to/afl_directory make afl

Fuzzing with [libFuzzer] is also supported but, because libFuzzer is still
under active development, may not work with your system-installed version of
clang. Assuming LLVM has been built in `$HOME/src/llvm/build` the fuzzer can be
run with:

CC="$HOME/src/llvm/build/bin/clang" LIB_FUZZER_PATH="$HOME/src/llvm/lib/Fuzzer/libFuzzer.a" make libFuzzer

To make a release tarball and zip archive:

make archive
Expand Down Expand Up @@ -188,3 +195,4 @@ most of the C library's API and its test harness.
[Build Status]: https://img.shields.io/travis/jgm/cmark/master.svg?style=flat
[Windows Build Status]: https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true
[american fuzzy lop]: http://lcamtuf.coredump.cx/afl/
[libFuzzer]: http://llvm.org/docs/LibFuzzer.html
11 changes: 11 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,14 @@ endif()
if(CMAKE_BUILD_TYPE STREQUAL "Ubsan")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
endif()

if(CMARK_LIB_FUZZER)
set(FUZZ_HARNESS "cmark-fuzz")
add_executable(${FUZZ_HARNESS} ../test/cmark-fuzz.c ${LIBRARY_SOURCES})
target_link_libraries(${FUZZ_HARNESS} "${CMAKE_LIB_FUZZER_PATH}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-coverage=trace-pc-guard")

# cmark is written in C but the libFuzzer runtime is written in C++ which
# needs to link against the C++ runtime. Explicitly link it into cmark-fuzz
set_target_properties(${FUZZ_HARNESS} PROPERTIES LINK_FLAGS "-lstdc++")
endif()
28 changes: 28 additions & 0 deletions test/cmark-fuzz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <stdint.h>
#include <stdlib.h>
#include "cmark.h"

int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
int options = 0;
if (size > sizeof(options)) {
/* First 4 bytes of input are treated as options */
int options = *(const int *)data;

/* Mask off valid option bits */
options = options & (CMARK_OPT_SOURCEPOS | CMARK_OPT_HARDBREAKS | CMARK_OPT_SAFE | CMARK_OPT_NOBREAKS | CMARK_OPT_NORMALIZE | CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_SMART);

/* Remainder of input is the markdown */
const char *markdown = (const char *)(data + sizeof(options));
const size_t markdown_size = size - sizeof(options);
cmark_node *doc = cmark_parse_document(markdown, markdown_size, options);

free(cmark_render_commonmark(doc, options, 80));
free(cmark_render_html(doc, options));
free(cmark_render_latex(doc, options, 80));
free(cmark_render_man(doc, options, 80));
free(cmark_render_xml(doc, options));

cmark_node_free(doc);
}
return 0;
}
4 changes: 4 additions & 0 deletions test/run-cmark-fuzz
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -eu
CMARK_FUZZ="$1"
shift
ASAN_OPTIONS="quarantine_size_mb=10:detect_leaks=1" "${CMARK_FUZZ}" -max_len=256 -timeout=1 -dict=test/fuzzing_dictionary "$@"

0 comments on commit c1dea4e

Please sign in to comment.