diff --git a/contrib/fuzz/Makefile b/contrib/fuzz/Makefile --- a/contrib/fuzz/Makefile +++ b/contrib/fuzz/Makefile @@ -13,8 +13,28 @@ $$CXX $$CXXFLAGS -std=c++11 -I../../mercurial bdiff.cc \ bdiff-oss-fuzz.o -lFuzzingEngine -o $$OUT/bdiff_fuzzer -all: bdiff +x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h + clang -g -O1 -fsanitize=fuzzer-no-link,address -c \ + -o $@ \ + $< + +xdiff: xdiff.cc xdiffi.o xemit.o xmerge.o xprepare.o xutils.o + clang -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \ + -I../../mercurial xdiff.cc \ + xdiffi.o xemit.o xmerge.o xprepare.o xutils.o -o xdiff -oss-fuzz: bdiff_fuzzer +fuzz-x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h + $$CC $$CFLAGS -c \ + -o $@ \ + $< + +xdiff_fuzzer: xdiff.cc fuzz-xdiffi.o fuzz-xemit.o fuzz-xmerge.o fuzz-xprepare.o fuzz-xutils.o + $$CXX $$CXXFLAGS -std=c++11 -I../../mercurial xdiff.cc \ + fuzz-xdiffi.o fuzz-xemit.o fuzz-xmerge.o fuzz-xprepare.o fuzz-xutils.o \ + -lFuzzingEngine -o $$OUT/xdiff_fuzzer + +all: bdiff xdiff + +oss-fuzz: bdiff_fuzzer xdiff_fuzzer .PHONY: all oss-fuzz diff --git a/contrib/fuzz/xdiff.cc b/contrib/fuzz/xdiff.cc new file mode 100644 --- /dev/null +++ b/contrib/fuzz/xdiff.cc @@ -0,0 +1,67 @@ +/* + * xdiff.cc - fuzzer harness for thirdparty/xdiff + * + * Copyright 2018, Google Inc. + * + * This software may be used and distributed according to the terms of + * the GNU General Public License, incorporated herein by reference. + */ +#include "thirdparty/xdiff/xdiff.h" +#include +#include + +extern "C" { + +int hunk_consumer(long a1, long a2, long b1, long b2, void *priv) +{ + // TODO: probably also test returning -1 from this when things break? + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ + if (!Size) { + return 0; + } + // figure out a random point in [0, Size] to split our input. + size_t split = Data[0] / 255.0 * Size; + + mmfile_t a, b; + + // `a` input to diff is data[1:split] + a.ptr = (char *)Data + 1; + // which has len split-1 + a.size = split - 1; + // `b` starts at the next byte after `a` ends + b.ptr = a.ptr + a.size; + b.size = Size - split; + xpparam_t xpp = { + XDF_INDENT_HEURISTIC, /* flags */ + NULL, /* anchors */ + 0, /* anchors_nr */ + }; + xdemitconf_t xecfg = { + 0, /* ctxlen */ + 0, /* interhunkctxlen */ + XDL_EMIT_BDIFFHUNK, /* flags */ + NULL, /* find_func */ + NULL, /* find_func_priv */ + hunk_consumer, /* hunk_consume_func */ + }; + xdemitcb_t ecb = { + NULL, /* priv */ + NULL, /* outf */ + }; + xdl_diff(&a, &b, &xpp, &xecfg, &ecb); + return 0; // Non-zero return values are reserved for future use. +} + +#ifdef HG_FUZZER_INCLUDE_MAIN +int main(int argc, char **argv) +{ + const char data[] = "asdf"; + return LLVMFuzzerTestOneInput((const uint8_t *)data, 4); +} +#endif + +} // extern "C"