From 00ed736eecf93aeab49089abb06e0e5fc0e7e091 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Fri, 5 Jun 2020 12:49:25 +0200 Subject: [PATCH] Add a couple of libFuzzer targets - XML fuzzer Currently tests the pull parser, push parser and reader, as well as serialization. Supports splitting fuzz data into multiple documents for things like external DTDs or entities. The seed corpus is built from parts of the test suite. - Regexp fuzzer Seed corpus was statically generated from test suite. - URI fuzzer Tests parsing and most other functions from uri.c. --- Makefile.am | 3 +- configure.ac | 2 +- fuzz/.gitignore | 7 + fuzz/Makefile.am | 75 ++++++++++ fuzz/README | 19 +++ fuzz/fuzz.c | 274 ++++++++++++++++++++++++++++++++++ fuzz/fuzz.h | 55 +++++++ fuzz/regexp.c | 40 +++++ fuzz/regexp.dict | 16 ++ fuzz/seed/regexp/branch-1 | Bin 0 -> 21 bytes fuzz/seed/regexp/branch-10 | Bin 0 -> 22 bytes fuzz/seed/regexp/branch-11 | Bin 0 -> 21 bytes fuzz/seed/regexp/branch-12 | Bin 0 -> 22 bytes fuzz/seed/regexp/branch-13 | Bin 0 -> 22 bytes fuzz/seed/regexp/branch-2 | Bin 0 -> 21 bytes fuzz/seed/regexp/branch-3 | Bin 0 -> 22 bytes fuzz/seed/regexp/branch-4 | Bin 0 -> 22 bytes fuzz/seed/regexp/branch-5 | Bin 0 -> 23 bytes fuzz/seed/regexp/branch-6 | Bin 0 -> 23 bytes fuzz/seed/regexp/branch-7 | Bin 0 -> 23 bytes fuzz/seed/regexp/branch-8 | Bin 0 -> 21 bytes fuzz/seed/regexp/branch-9 | Bin 0 -> 22 bytes fuzz/seed/regexp/bug316338-1 | Bin 0 -> 71 bytes fuzz/seed/regexp/bug316338-10 | Bin 0 -> 487 bytes fuzz/seed/regexp/bug316338-11 | Bin 0 -> 85 bytes fuzz/seed/regexp/bug316338-12 | Bin 0 -> 88 bytes fuzz/seed/regexp/bug316338-13 | Bin 0 -> 89 bytes fuzz/seed/regexp/bug316338-14 | Bin 0 -> 93 bytes fuzz/seed/regexp/bug316338-15 | Bin 0 -> 500 bytes fuzz/seed/regexp/bug316338-16 | Bin 0 -> 1355 bytes fuzz/seed/regexp/bug316338-2 | Bin 0 -> 74 bytes fuzz/seed/regexp/bug316338-3 | Bin 0 -> 75 bytes fuzz/seed/regexp/bug316338-4 | Bin 0 -> 79 bytes fuzz/seed/regexp/bug316338-5 | Bin 0 -> 487 bytes fuzz/seed/regexp/bug316338-6 | Bin 0 -> 71 bytes fuzz/seed/regexp/bug316338-7 | Bin 0 -> 74 bytes fuzz/seed/regexp/bug316338-8 | Bin 0 -> 75 bytes fuzz/seed/regexp/bug316338-9 | Bin 0 -> 79 bytes fuzz/seed/regexp/bug420596-1 | Bin 0 -> 25 bytes fuzz/seed/regexp/bug420596-2 | Bin 0 -> 25 bytes fuzz/seed/regexp/bug420596-3 | Bin 0 -> 25 bytes fuzz/seed/regexp/bug420596-4 | Bin 0 -> 25 bytes fuzz/seed/regexp/bug420596-5 | Bin 0 -> 23 bytes fuzz/seed/regexp/bug420596-6 | Bin 0 -> 23 bytes fuzz/seed/regexp/bug420596-7 | Bin 0 -> 23 bytes fuzz/seed/regexp/bug420596-8 | Bin 0 -> 23 bytes fuzz/seed/regexp/content-1 | Bin 0 -> 17 bytes fuzz/seed/regexp/content-10 | Bin 0 -> 33 bytes fuzz/seed/regexp/content-2 | Bin 0 -> 17 bytes fuzz/seed/regexp/content-3 | Bin 0 -> 18 bytes fuzz/seed/regexp/content-4 | Bin 0 -> 17 bytes fuzz/seed/regexp/content-5 | Bin 0 -> 32 bytes fuzz/seed/regexp/content-6 | Bin 0 -> 33 bytes fuzz/seed/regexp/content-7 | Bin 0 -> 34 bytes fuzz/seed/regexp/content-8 | Bin 0 -> 35 bytes fuzz/seed/regexp/content-9 | Bin 0 -> 40 bytes fuzz/seed/regexp/hard-1 | Bin 0 -> 37 bytes fuzz/seed/regexp/hard-10 | Bin 0 -> 28 bytes fuzz/seed/regexp/hard-2 | Bin 0 -> 38 bytes fuzz/seed/regexp/hard-3 | Bin 0 -> 41 bytes fuzz/seed/regexp/hard-4 | Bin 0 -> 37 bytes fuzz/seed/regexp/hard-5 | Bin 0 -> 40 bytes fuzz/seed/regexp/hard-6 | Bin 0 -> 39 bytes fuzz/seed/regexp/hard-7 | Bin 0 -> 29 bytes fuzz/seed/regexp/hard-8 | Bin 0 -> 33 bytes fuzz/seed/regexp/hard-9 | Bin 0 -> 27 bytes fuzz/seed/regexp/ncname-1 | Bin 0 -> 19 bytes fuzz/seed/regexp/ncname-2 | Bin 0 -> 21 bytes fuzz/seed/regexp/ncname-3 | Bin 0 -> 23 bytes fuzz/seed/regexp/ncname-4 | Bin 0 -> 21 bytes fuzz/seed/regexp/ncname-5 | Bin 0 -> 23 bytes fuzz/seed/regexp/ranges-1 | Bin 0 -> 8 bytes fuzz/seed/regexp/ranges-10 | Bin 0 -> 18 bytes fuzz/seed/regexp/ranges-11 | Bin 0 -> 16 bytes fuzz/seed/regexp/ranges-12 | Bin 0 -> 19 bytes fuzz/seed/regexp/ranges-2 | Bin 0 -> 9 bytes fuzz/seed/regexp/ranges-3 | Bin 0 -> 10 bytes fuzz/seed/regexp/ranges-4 | Bin 0 -> 11 bytes fuzz/seed/regexp/ranges-5 | Bin 0 -> 12 bytes fuzz/seed/regexp/ranges-6 | Bin 0 -> 13 bytes fuzz/seed/regexp/ranges-7 | Bin 0 -> 14 bytes fuzz/seed/regexp/ranges-8 | Bin 0 -> 15 bytes fuzz/seed/regexp/ranges-9 | Bin 0 -> 17 bytes fuzz/seed/regexp/ranges2-1 | Bin 0 -> 17 bytes fuzz/seed/regexp/ranges2-10 | Bin 0 -> 42 bytes fuzz/seed/regexp/ranges2-11 | Bin 0 -> 43 bytes fuzz/seed/regexp/ranges2-12 | Bin 0 -> 43 bytes fuzz/seed/regexp/ranges2-2 | Bin 0 -> 18 bytes fuzz/seed/regexp/ranges2-3 | Bin 0 -> 17 bytes fuzz/seed/regexp/ranges2-4 | Bin 0 -> 18 bytes fuzz/seed/regexp/ranges2-5 | Bin 0 -> 19 bytes fuzz/seed/regexp/ranges2-6 | Bin 0 -> 20 bytes fuzz/seed/regexp/ranges2-7 | Bin 0 -> 18 bytes fuzz/seed/regexp/ranges2-8 | Bin 0 -> 18 bytes fuzz/seed/regexp/ranges2-9 | Bin 0 -> 41 bytes fuzz/seed/regexp/xpath-1 | Bin 0 -> 181 bytes fuzz/seed/regexp/xpath-10 | Bin 0 -> 212 bytes fuzz/seed/regexp/xpath-11 | Bin 0 -> 181 bytes fuzz/seed/regexp/xpath-12 | Bin 0 -> 183 bytes fuzz/seed/regexp/xpath-13 | Bin 0 -> 183 bytes fuzz/seed/regexp/xpath-14 | Bin 0 -> 182 bytes fuzz/seed/regexp/xpath-15 | Bin 0 -> 191 bytes fuzz/seed/regexp/xpath-16 | Bin 0 -> 181 bytes fuzz/seed/regexp/xpath-17 | Bin 0 -> 241 bytes fuzz/seed/regexp/xpath-18 | Bin 0 -> 204 bytes fuzz/seed/regexp/xpath-19 | Bin 0 -> 262 bytes fuzz/seed/regexp/xpath-2 | Bin 0 -> 241 bytes fuzz/seed/regexp/xpath-20 | Bin 0 -> 181 bytes fuzz/seed/regexp/xpath-21 | Bin 0 -> 277 bytes fuzz/seed/regexp/xpath-22 | Bin 0 -> 337 bytes fuzz/seed/regexp/xpath-23 | Bin 0 -> 277 bytes fuzz/seed/regexp/xpath-24 | Bin 0 -> 279 bytes fuzz/seed/regexp/xpath-25 | Bin 0 -> 282 bytes fuzz/seed/regexp/xpath-26 | Bin 0 -> 281 bytes fuzz/seed/regexp/xpath-27 | Bin 0 -> 281 bytes fuzz/seed/regexp/xpath-28 | Bin 0 -> 287 bytes fuzz/seed/regexp/xpath-29 | Bin 0 -> 295 bytes fuzz/seed/regexp/xpath-3 | Bin 0 -> 181 bytes fuzz/seed/regexp/xpath-30 | Bin 0 -> 308 bytes fuzz/seed/regexp/xpath-31 | Bin 0 -> 277 bytes fuzz/seed/regexp/xpath-32 | Bin 0 -> 279 bytes fuzz/seed/regexp/xpath-33 | Bin 0 -> 279 bytes fuzz/seed/regexp/xpath-34 | Bin 0 -> 278 bytes fuzz/seed/regexp/xpath-35 | Bin 0 -> 287 bytes fuzz/seed/regexp/xpath-4 | Bin 0 -> 183 bytes fuzz/seed/regexp/xpath-5 | Bin 0 -> 186 bytes fuzz/seed/regexp/xpath-6 | Bin 0 -> 185 bytes fuzz/seed/regexp/xpath-7 | Bin 0 -> 185 bytes fuzz/seed/regexp/xpath-8 | Bin 0 -> 191 bytes fuzz/seed/regexp/xpath-9 | Bin 0 -> 199 bytes fuzz/seed/uri/dot | 1 + fuzz/seed/uri/full | Bin 0 -> 36 bytes fuzz/testFuzzer.c | 55 +++++++ fuzz/uri.c | 45 ++++++ fuzz/xml.c | 90 +++++++++++ fuzz/xml.dict | 76 ++++++++++ fuzz/xmlSeed.c | 94 ++++++++++++ 137 files changed, 850 insertions(+), 2 deletions(-) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Makefile.am create mode 100644 fuzz/README create mode 100644 fuzz/fuzz.c create mode 100644 fuzz/fuzz.h create mode 100644 fuzz/regexp.c create mode 100644 fuzz/regexp.dict create mode 100644 fuzz/seed/regexp/branch-1 create mode 100644 fuzz/seed/regexp/branch-10 create mode 100644 fuzz/seed/regexp/branch-11 create mode 100644 fuzz/seed/regexp/branch-12 create mode 100644 fuzz/seed/regexp/branch-13 create mode 100644 fuzz/seed/regexp/branch-2 create mode 100644 fuzz/seed/regexp/branch-3 create mode 100644 fuzz/seed/regexp/branch-4 create mode 100644 fuzz/seed/regexp/branch-5 create mode 100644 fuzz/seed/regexp/branch-6 create mode 100644 fuzz/seed/regexp/branch-7 create mode 100644 fuzz/seed/regexp/branch-8 create mode 100644 fuzz/seed/regexp/branch-9 create mode 100644 fuzz/seed/regexp/bug316338-1 create mode 100644 fuzz/seed/regexp/bug316338-10 create mode 100644 fuzz/seed/regexp/bug316338-11 create mode 100644 fuzz/seed/regexp/bug316338-12 create mode 100644 fuzz/seed/regexp/bug316338-13 create mode 100644 fuzz/seed/regexp/bug316338-14 create mode 100644 fuzz/seed/regexp/bug316338-15 create mode 100644 fuzz/seed/regexp/bug316338-16 create mode 100644 fuzz/seed/regexp/bug316338-2 create mode 100644 fuzz/seed/regexp/bug316338-3 create mode 100644 fuzz/seed/regexp/bug316338-4 create mode 100644 fuzz/seed/regexp/bug316338-5 create mode 100644 fuzz/seed/regexp/bug316338-6 create mode 100644 fuzz/seed/regexp/bug316338-7 create mode 100644 fuzz/seed/regexp/bug316338-8 create mode 100644 fuzz/seed/regexp/bug316338-9 create mode 100644 fuzz/seed/regexp/bug420596-1 create mode 100644 fuzz/seed/regexp/bug420596-2 create mode 100644 fuzz/seed/regexp/bug420596-3 create mode 100644 fuzz/seed/regexp/bug420596-4 create mode 100644 fuzz/seed/regexp/bug420596-5 create mode 100644 fuzz/seed/regexp/bug420596-6 create mode 100644 fuzz/seed/regexp/bug420596-7 create mode 100644 fuzz/seed/regexp/bug420596-8 create mode 100644 fuzz/seed/regexp/content-1 create mode 100644 fuzz/seed/regexp/content-10 create mode 100644 fuzz/seed/regexp/content-2 create mode 100644 fuzz/seed/regexp/content-3 create mode 100644 fuzz/seed/regexp/content-4 create mode 100644 fuzz/seed/regexp/content-5 create mode 100644 fuzz/seed/regexp/content-6 create mode 100644 fuzz/seed/regexp/content-7 create mode 100644 fuzz/seed/regexp/content-8 create mode 100644 fuzz/seed/regexp/content-9 create mode 100644 fuzz/seed/regexp/hard-1 create mode 100644 fuzz/seed/regexp/hard-10 create mode 100644 fuzz/seed/regexp/hard-2 create mode 100644 fuzz/seed/regexp/hard-3 create mode 100644 fuzz/seed/regexp/hard-4 create mode 100644 fuzz/seed/regexp/hard-5 create mode 100644 fuzz/seed/regexp/hard-6 create mode 100644 fuzz/seed/regexp/hard-7 create mode 100644 fuzz/seed/regexp/hard-8 create mode 100644 fuzz/seed/regexp/hard-9 create mode 100644 fuzz/seed/regexp/ncname-1 create mode 100644 fuzz/seed/regexp/ncname-2 create mode 100644 fuzz/seed/regexp/ncname-3 create mode 100644 fuzz/seed/regexp/ncname-4 create mode 100644 fuzz/seed/regexp/ncname-5 create mode 100644 fuzz/seed/regexp/ranges-1 create mode 100644 fuzz/seed/regexp/ranges-10 create mode 100644 fuzz/seed/regexp/ranges-11 create mode 100644 fuzz/seed/regexp/ranges-12 create mode 100644 fuzz/seed/regexp/ranges-2 create mode 100644 fuzz/seed/regexp/ranges-3 create mode 100644 fuzz/seed/regexp/ranges-4 create mode 100644 fuzz/seed/regexp/ranges-5 create mode 100644 fuzz/seed/regexp/ranges-6 create mode 100644 fuzz/seed/regexp/ranges-7 create mode 100644 fuzz/seed/regexp/ranges-8 create mode 100644 fuzz/seed/regexp/ranges-9 create mode 100644 fuzz/seed/regexp/ranges2-1 create mode 100644 fuzz/seed/regexp/ranges2-10 create mode 100644 fuzz/seed/regexp/ranges2-11 create mode 100644 fuzz/seed/regexp/ranges2-12 create mode 100644 fuzz/seed/regexp/ranges2-2 create mode 100644 fuzz/seed/regexp/ranges2-3 create mode 100644 fuzz/seed/regexp/ranges2-4 create mode 100644 fuzz/seed/regexp/ranges2-5 create mode 100644 fuzz/seed/regexp/ranges2-6 create mode 100644 fuzz/seed/regexp/ranges2-7 create mode 100644 fuzz/seed/regexp/ranges2-8 create mode 100644 fuzz/seed/regexp/ranges2-9 create mode 100644 fuzz/seed/regexp/xpath-1 create mode 100644 fuzz/seed/regexp/xpath-10 create mode 100644 fuzz/seed/regexp/xpath-11 create mode 100644 fuzz/seed/regexp/xpath-12 create mode 100644 fuzz/seed/regexp/xpath-13 create mode 100644 fuzz/seed/regexp/xpath-14 create mode 100644 fuzz/seed/regexp/xpath-15 create mode 100644 fuzz/seed/regexp/xpath-16 create mode 100644 fuzz/seed/regexp/xpath-17 create mode 100644 fuzz/seed/regexp/xpath-18 create mode 100644 fuzz/seed/regexp/xpath-19 create mode 100644 fuzz/seed/regexp/xpath-2 create mode 100644 fuzz/seed/regexp/xpath-20 create mode 100644 fuzz/seed/regexp/xpath-21 create mode 100644 fuzz/seed/regexp/xpath-22 create mode 100644 fuzz/seed/regexp/xpath-23 create mode 100644 fuzz/seed/regexp/xpath-24 create mode 100644 fuzz/seed/regexp/xpath-25 create mode 100644 fuzz/seed/regexp/xpath-26 create mode 100644 fuzz/seed/regexp/xpath-27 create mode 100644 fuzz/seed/regexp/xpath-28 create mode 100644 fuzz/seed/regexp/xpath-29 create mode 100644 fuzz/seed/regexp/xpath-3 create mode 100644 fuzz/seed/regexp/xpath-30 create mode 100644 fuzz/seed/regexp/xpath-31 create mode 100644 fuzz/seed/regexp/xpath-32 create mode 100644 fuzz/seed/regexp/xpath-33 create mode 100644 fuzz/seed/regexp/xpath-34 create mode 100644 fuzz/seed/regexp/xpath-35 create mode 100644 fuzz/seed/regexp/xpath-4 create mode 100644 fuzz/seed/regexp/xpath-5 create mode 100644 fuzz/seed/regexp/xpath-6 create mode 100644 fuzz/seed/regexp/xpath-7 create mode 100644 fuzz/seed/regexp/xpath-8 create mode 100644 fuzz/seed/regexp/xpath-9 create mode 100644 fuzz/seed/uri/dot create mode 100644 fuzz/seed/uri/full create mode 100644 fuzz/testFuzzer.c create mode 100644 fuzz/uri.c create mode 100644 fuzz/xml.c create mode 100644 fuzz/xml.dict create mode 100644 fuzz/xmlSeed.c diff --git a/Makefile.am b/Makefile.am index be1a883d..2a9d4709 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = include . doc example xstc $(PYTHON_SUBDIR) +SUBDIRS = include . doc example fuzz xstc $(PYTHON_SUBDIR) DIST_SUBDIRS = include . doc example python xstc @@ -210,6 +210,7 @@ runtests: runtest$(EXEEXT) testrecurse$(EXEEXT) testapi$(EXEEXT) \ $(CHECKER) ./runxmlconf$(EXEEXT) @(if [ "$(PYTHON_SUBDIR)" != "" ] ; then cd python ; \ $(MAKE) tests ; fi) + @cd fuzz; $(MAKE) tests check: all runtests diff --git a/configure.ac b/configure.ac index 5f95fee0..3a3d91d3 100644 --- a/configure.ac +++ b/configure.ac @@ -1714,7 +1714,7 @@ rm -f COPYING.LIB COPYING ln -s $srcdir/Copyright COPYING # keep on one line for cygwin c.f. #130896 -AC_CONFIG_FILES([libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake]) +AC_CONFIG_FILES([libxml2.spec:libxml.spec.in Makefile include/Makefile include/libxml/Makefile doc/Makefile doc/examples/Makefile doc/devhelp/Makefile example/Makefile fuzz/Makefile python/Makefile python/tests/Makefile xstc/Makefile include/libxml/xmlversion.h libxml-2.0.pc libxml-2.0-uninstalled.pc libxml2-config.cmake]) AC_CONFIG_FILES([python/setup.py], [chmod +x python/setup.py]) AC_CONFIG_FILES([xml2-config], [chmod +x xml2-config]) AC_OUTPUT diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000..28b71084 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,7 @@ +corpus/ +regexp +seed/xml* +testFuzzer +uri +xml +xmlSeed diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am new file mode 100644 index 00000000..0e7391ba --- /dev/null +++ b/fuzz/Makefile.am @@ -0,0 +1,75 @@ +EXTRA_PROGRAMS = regexp uri xml xmlSeed +check_PROGRAMS = testFuzzer +CLEANFILES = $(EXTRA_PROGRAMS) +AM_CPPFLAGS = -I$(top_srcdir)/include +DEPENDENCIES = $(top_builddir)/libxml2.la +LDADD = $(STATIC_BINARIES) $(top_builddir)/libxml2.la $(THREAD_LIBS) $(Z_LIBS) $(LZMA_LIBS) $(ICONV_LIBS) $(M_LIBS) $(WIN32_EXTRA_LIBADD) + +PARSER_FUZZER_MAX_LEN = 100000 +XML_SEED_CORPUS_SRC = \ + $(top_srcdir)/test/* \ + $(top_srcdir)/test/errors/*.xml \ + $(top_srcdir)/test/errors10/*.xml \ + $(top_srcdir)/test/namespaces/* \ + $(top_srcdir)/test/valid/*.xml \ + $(top_srcdir)/test/xmlid/* \ + $(top_srcdir)/test/VC/* \ + $(top_srcdir)/test/VCM/* + +xmlSeed_SOURCES = xmlSeed.c fuzz.c + +seed/xml.stamp: xmlSeed$(EXEEXT) + @mkdir -p seed/xml + @for i in $(XML_SEED_CORPUS_SRC); do \ + if [ -f $$i ]; then \ + echo Processing seed $$i; \ + base=$$(basename $$i) \ + outfile=$(abs_builddir)/seed/xml/$$base; \ + pushd $$(dirname $$i) >/dev/null; \ + $(abs_builddir)/xmlSeed$(EXEEXT) $$base > $$outfile; \ + popd >/dev/null; \ + if [ "$$(wc -c < $$outfile)" -gt $(PARSER_FUZZER_MAX_LEN) ]; then \ + rm $$outfile; \ + fi; \ + fi; \ + done + @touch seed/xml.stamp + +testFuzzer_SOURCES = testFuzzer.c fuzz.c + +tests: testFuzzer$(EXEEXT) + @echo "## Running fuzzer tests" + @./testFuzzer$(EXEEXT) + +xml_SOURCES = xml.c fuzz.c +xml_LDFLAGS = -fsanitize=fuzzer + +fuzz-xml: xml$(EXEEXT) seed/xml.stamp + @mkdir -p corpus/xml + ./xml$(EXEEXT) \ + -dict=xml.dict \ + -max_len=$(PARSER_FUZZER_MAX_LEN) \ + -timeout=20 \ + corpus/xml seed/xml + +regexp_SOURCES = regexp.c fuzz.c +regexp_LDFLAGS = -fsanitize=fuzzer + +fuzz-regexp: regexp$(EXEEXT) + @mkdir -p corpus/regexp + ./regexp$(EXEEXT) \ + -dict=regexp.dict \ + -max_len=10000 \ + -timeout=20 \ + corpus/regexp $(srcdir)/seed/regexp + +uri_SOURCES = uri.c fuzz.c +uri_LDFLAGS = -fsanitize=fuzzer + +fuzz-uri: uri$(EXEEXT) + @mkdir -p corpus/uri + ./uri$(EXEEXT) \ + -max_len=10000 \ + -timeout=2 \ + corpus/uri $(srcdir)/seed/uri + diff --git a/fuzz/README b/fuzz/README new file mode 100644 index 00000000..f675ad82 --- /dev/null +++ b/fuzz/README @@ -0,0 +1,19 @@ +libFuzzer instructions for libxml2 +================================== + +Set compiler and options: + + export CC=clang + export CFLAGS="-g -fsanitize=fuzzer-no-link,address,undefined \ + -fno-sanitize-recover=all \ + -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" + +Build libxml2 with instrumentation: + + ./configure --without-python + make + +Run fuzzers: + + make -C fuzz fuzz-xml + diff --git a/fuzz/fuzz.c b/fuzz/fuzz.c new file mode 100644 index 00000000..6955f280 --- /dev/null +++ b/fuzz/fuzz.c @@ -0,0 +1,274 @@ +/* + * fuzz.c: Common functions for fuzzing. + * + * See Copyright for the status of this software. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "fuzz.h" + +typedef struct { + const char *data; + size_t size; +} xmlFuzzEntityInfo; + +/* Single static instance for now */ +static struct { + /* Original data */ + const char *data; + size_t size; + + /* Remaining data */ + const char *ptr; + size_t remaining; + + /* Buffer for unescaped strings */ + char *outBuf; + char *outPtr; /* Free space at end of buffer */ + + xmlHashTablePtr entities; /* Maps URLs to xmlFuzzEntityInfos */ + + /* The first entity is the main entity. */ + const char *mainUrl; + xmlFuzzEntityInfo *mainEntity; +} fuzzData; + +/** + * xmlFuzzErrorFunc: + * + * An error function that simply discards all errors. + */ +void +xmlFuzzErrorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED, + ...) { +} + +/** + * xmlFuzzDataInit: + * + * Initialize fuzz data provider. + */ +void +xmlFuzzDataInit(const char *data, size_t size) { + fuzzData.data = data; + fuzzData.size = size; + fuzzData.ptr = data; + fuzzData.remaining = size; + + fuzzData.outBuf = xmlMalloc(size + 1); + fuzzData.outPtr = fuzzData.outBuf; + + fuzzData.entities = xmlHashCreate(8); + fuzzData.mainUrl = NULL; + fuzzData.mainEntity = NULL; +} + +static void +xmlFreeEntityEntry(void *value, const xmlChar *name) { + xmlFree(value); +} + +/** + * xmlFuzzDataFree: + * + * Cleanup fuzz data provider. + */ +void +xmlFuzzDataCleanup(void) { + xmlFree(fuzzData.outBuf); + xmlHashFree(fuzzData.entities, xmlFreeEntityEntry); +} + +/** + * xmlFuzzReadInt: + * @size: size of string in bytes + * + * Read an integer from the fuzz data. + */ +int +xmlFuzzReadInt() { + int ret; + + if (fuzzData.remaining < sizeof(int)) + return(0); + memcpy(&ret, fuzzData.ptr, sizeof(int)); + fuzzData.ptr += sizeof(int); + fuzzData.remaining -= sizeof(int); + + return ret; +} + +/** + * xmlFuzzReadString: + * @size: size of string in bytes + * + * Read a random-length string from the fuzz data. + * + * The format is similar to libFuzzer's FuzzedDataProvider but treats + * backslash followed by newline as end of string. This makes the fuzz data + * more readable. A backslash character is escaped with another backslash. + * + * Returns a zero-terminated string or NULL if the fuzz data is exhausted. + */ +static const char * +xmlFuzzReadString(size_t *size) { + const char *out = fuzzData.outPtr; + + while (fuzzData.remaining > 0) { + int c = *fuzzData.ptr++; + fuzzData.remaining--; + + if ((c == '\\') && (fuzzData.remaining > 0)) { + int c2 = *fuzzData.ptr; + + if (c2 == '\n') { + fuzzData.ptr++; + fuzzData.remaining--; + *size = fuzzData.outPtr - out; + *fuzzData.outPtr++ = '\0'; + return(out); + } + if (c2 == '\\') { + fuzzData.ptr++; + fuzzData.remaining--; + } + } + + *fuzzData.outPtr++ = c; + } + + if (fuzzData.outPtr > out) { + *size = fuzzData.outPtr - out; + *fuzzData.outPtr++ = '\0'; + return(out); + } + + return(NULL); +} + +/** + * xmlFuzzReadEntities: + * + * Read entities like the main XML file, external DTDs, external parsed + * entities from fuzz data. + */ +void +xmlFuzzReadEntities(void) { + size_t num = 0; + + while (1) { + const char *url, *entity; + size_t urlSize, entitySize; + xmlFuzzEntityInfo *entityInfo; + + url = xmlFuzzReadString(&urlSize); + if (url == NULL) break; + + entity = xmlFuzzReadString(&entitySize); + if (entity == NULL) break; + + if (xmlHashLookup(fuzzData.entities, (xmlChar *)url) == NULL) { + entityInfo = xmlMalloc(sizeof(xmlFuzzEntityInfo)); + entityInfo->data = entity; + entityInfo->size = entitySize; + + xmlHashAddEntry(fuzzData.entities, (xmlChar *)url, entityInfo); + + if (num == 0) { + fuzzData.mainUrl = url; + fuzzData.mainEntity = entityInfo; + } + + num++; + } + } +} + +/** + * xmlFuzzMainEntity: + * @size: size of the main entity in bytes + * + * Returns the main entity. + */ +const char * +xmlFuzzMainEntity(size_t *size) { + if (fuzzData.mainEntity == NULL) + return(NULL); + *size = fuzzData.mainEntity->size; + return(fuzzData.mainEntity->data); +} + +/** + * xmlFuzzEntityLoader: + * + * The entity loader for fuzz data. + */ +xmlParserInputPtr +xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED, + xmlParserCtxtPtr ctxt) { + xmlParserInputPtr input; + xmlFuzzEntityInfo *entity; + + if (URL == NULL) + return(NULL); + entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL); + if (entity == NULL) + return(NULL); + + input = xmlNewInputStream(ctxt); + input->filename = NULL; + input->buf = xmlParserInputBufferCreateMem(entity->data, entity->size, + XML_CHAR_ENCODING_NONE); + input->base = input->cur = xmlBufContent(input->buf->buffer); + input->end = input->base + entity->size; + + return input; +} + +/** + * xmlFuzzExtractStrings: + * + * Extract C strings from input data. Use exact-size allocations to detect + * potential memory errors. + */ +size_t +xmlFuzzExtractStrings(const char *data, size_t size, char **strings, + size_t numStrings) { + const char *start = data; + const char *end = data + size; + size_t i = 0, ret; + + while (i < numStrings) { + size_t strSize = end - start; + const char *zero = memchr(start, 0, strSize); + + if (zero != NULL) + strSize = zero - start; + + strings[i] = xmlMalloc(strSize + 1); + memcpy(strings[i], start, strSize); + strings[i][strSize] = '\0'; + + i++; + if (zero != NULL) + start = zero + 1; + else + break; + } + + ret = i; + + while (i < numStrings) { + strings[i] = NULL; + i++; + } + + return(ret); +} + diff --git a/fuzz/fuzz.h b/fuzz/fuzz.h new file mode 100644 index 00000000..1093be14 --- /dev/null +++ b/fuzz/fuzz.h @@ -0,0 +1,55 @@ +/* + * fuzz.h: Common functions and macros for fuzzing. + * + * See Copyright for the status of this software. + */ + +#ifndef __XML_FUZZERCOMMON_H__ +#define __XML_FUZZERCOMMON_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int +LLVMFuzzerInitialize(int *argc, char ***argv); + +int +LLVMFuzzerTestOneInput(const char *data, size_t size); + +void +xmlFuzzErrorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED, + ...); + +void +xmlFuzzDataInit(const char *data, size_t size); + +void +xmlFuzzDataCleanup(void); + +int +xmlFuzzReadInt(void); + +void +xmlFuzzReadEntities(void); + +const char * +xmlFuzzMainEntity(size_t *size); + +xmlParserInputPtr +xmlFuzzEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED, + xmlParserCtxtPtr ctxt); + +size_t +xmlFuzzExtractStrings(const char *data, size_t size, char **strings, + size_t numStrings); + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_FUZZERCOMMON_H__ */ + diff --git a/fuzz/regexp.c b/fuzz/regexp.c new file mode 100644 index 00000000..ed13f637 --- /dev/null +++ b/fuzz/regexp.c @@ -0,0 +1,40 @@ +/* + * regexp.c: a libFuzzer target to test the regexp module. + * + * See Copyright for the status of this software. + */ + +#include +#include "fuzz.h" + +int +LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED, + char ***argv ATTRIBUTE_UNUSED) { + xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc); + + return 0; +} + +int +LLVMFuzzerTestOneInput(const char *data, size_t size) { + xmlRegexpPtr regexp; + char *str[2] = { NULL, NULL }; + size_t numStrings; + + numStrings = xmlFuzzExtractStrings(data, size, str, 2); + + regexp = xmlRegexpCompile(BAD_CAST str[0]); + /* xmlRegexpExec has pathological performance in too many cases. */ +#if 0 + if ((regexp != NULL) && (numStrings >= 2)) { + xmlRegexpExec(regexp, BAD_CAST str[1]); + } +#endif + xmlRegFreeRegexp(regexp); + + xmlFree(str[0]); + xmlFree(str[1]); + + return 0; +} + diff --git a/fuzz/regexp.dict b/fuzz/regexp.dict new file mode 100644 index 00000000..06b74a6c --- /dev/null +++ b/fuzz/regexp.dict @@ -0,0 +1,16 @@ +quant_any="*" +quant_opt="?" +quant_some="+" +quant_num="{1,2}" + +branch="|a" +pos_group="[a]" +neg_group="[^a]" + +cat_letter="\\p{L}" +cat_mark="\\p{M}" +cat_number="\\p{N}" +cat_punct="\\p{P}" +cat_sym="\\p{S}" +cat_sep="\\p{Z}" +cat_other="\\p{C}" diff --git a/fuzz/seed/regexp/branch-1 b/fuzz/seed/regexp/branch-1 new file mode 100644 index 0000000000000000000000000000000000000000..ded775eaf70f5e239ff1896eceaec934f6d4680e GIT binary patch literal 21 ccmYeSNzzEEN!3WN$*9THtVz?XNoGg{09CRFc>n+a literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-10 b/fuzz/seed/regexp/branch-10 new file mode 100644 index 0000000000000000000000000000000000000000..6700d77519c016dcb21460494592b96fc205dc5a GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGjO1OQ!@2jc($ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-11 b/fuzz/seed/regexp/branch-11 new file mode 100644 index 0000000000000000000000000000000000000000..d83f91819c609ca8a944dd4ceed5326853034f2f GIT binary patch literal 21 ccmYeSNzzEEN!3WN$*9THtVz?XNoGg`09CgKegFUf literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-12 b/fuzz/seed/regexp/branch-12 new file mode 100644 index 0000000000000000000000000000000000000000..b44dba5732268407ef24a8f274997aceea009e67 GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGh)0svi&2ipJu literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-13 b/fuzz/seed/regexp/branch-13 new file mode 100644 index 0000000000000000000000000000000000000000..64e50a0000896df6b5a82f044754cde30ec8c73e GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGh)1^``-2iyPv literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-2 b/fuzz/seed/regexp/branch-2 new file mode 100644 index 0000000000000000000000000000000000000000..8293d81dbfbabaf48c7f6062794256151aecebac GIT binary patch literal 21 ccmYeSNzzEEN!3WN$*9THtVz?XNoGg}09CXHdjJ3c literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-3 b/fuzz/seed/regexp/branch-3 new file mode 100644 index 0000000000000000000000000000000000000000..696af9bed4d7bae7ec063e2ade8784f4bcb509fc GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGh&0RUZ*2i^bx literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-4 b/fuzz/seed/regexp/branch-4 new file mode 100644 index 0000000000000000000000000000000000000000..83179988e4d3fb34a2d59f9acb418b2a80e12a6f GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGh&0{~r<2jBnz literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-5 b/fuzz/seed/regexp/branch-5 new file mode 100644 index 0000000000000000000000000000000000000000..6b6db8b981e9aa5a2cbe2cc8d1686e3c5cdc129a GIT binary patch literal 23 ecmYeSNzzEEN!3WN$*9THtVz?XNoGh&O$PvF*a$`d literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-6 b/fuzz/seed/regexp/branch-6 new file mode 100644 index 0000000000000000000000000000000000000000..4f477902eec648f3156e9b67e415184572972529 GIT binary patch literal 23 ecmYeSNzzEEN!3WN$*9THtVz?XNoGh&%>V#p*$77f literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-7 b/fuzz/seed/regexp/branch-7 new file mode 100644 index 0000000000000000000000000000000000000000..6334f7254a13f1a11379024ae43dfabab0859644 GIT binary patch literal 23 ecmYeSNzzEEN!3WN$*9THtVz?XNoGh&%>)2t+6YJh literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-8 b/fuzz/seed/regexp/branch-8 new file mode 100644 index 0000000000000000000000000000000000000000..f77a8f4d8ddede806ed6e4c2abc6494d86fc63a2 GIT binary patch literal 21 ccmYeSNzzEEN!3WN$*9THtVz?XNoGg_09CUGdH?_b literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/branch-9 b/fuzz/seed/regexp/branch-9 new file mode 100644 index 0000000000000000000000000000000000000000..acd0eeca2d9f467e4ebb7f05f10d78f998950259 GIT binary patch literal 22 dcmYeSNzzEEN!3WN$*9THtVz?XNoGh&1pr-=2j2hy literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-1 b/fuzz/seed/regexp/bug316338-1 new file mode 100644 index 0000000000000000000000000000000000000000..9f0a504abee16ef16152d41ed89a5eaaf34c07b1 GIT binary patch literal 71 zcmdPU&~UCv*3{65jwz1SiqW-?Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#MLCdS49j+7C! literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-10 b/fuzz/seed/regexp/bug316338-10 new file mode 100644 index 0000000000000000000000000000000000000000..60685bbe5a4fc97d72581cc96144f706baf04a44 GIT binary patch literal 487 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#H>z@ALJ0ufKw#$p literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-11 b/fuzz/seed/regexp/bug316338-11 new file mode 100644 index 0000000000000000000000000000000000000000..72a7956cbafe3a5b40bfb74c67de0b79b4bd3cd3 GIT binary patch literal 85 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhK@wUzU=o|OX0>sxrZ!kwQ&XG4 JS;55E7y!by70&sxrZ!kwQ&XG4 MS;55ESi#T;00kx%QUCw| literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-13 b/fuzz/seed/regexp/bug316338-13 new file mode 100644 index 0000000000000000000000000000000000000000..c91d4fea9140ddac84281cdec2e89fad29ffbf93 GIT binary patch literal 89 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhK@wUzU=o|OX0>sxrZ!kwQ&XG4 NS;55ESi#W97yuiq7KH!+ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-14 b/fuzz/seed/regexp/bug316338-14 new file mode 100644 index 0000000000000000000000000000000000000000..a164b42368422db69d175747837a3f9c5ebad84d GIT binary patch literal 93 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhK@wUzU=o|OX0>sxrZ!kwQ&XG4 RS;55ESi#W9Si!{93;=g~7eoL6 literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-15 b/fuzz/seed/regexp/bug316338-15 new file mode 100644 index 0000000000000000000000000000000000000000..750c76dedc5e77cdfa5d35b5681f86075a3959e4 GIT binary patch literal 500 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhK@wUzU=o|OX0>sxrZ!kwQ&XG4 sS;5@MM9<7b$HdrJ&(KK0+|WYLzyiTD)H5}L^JuMdKrJ6wuj8{F0BIIv;Q#;t literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-16 b/fuzz/seed/regexp/bug316338-16 new file mode 100644 index 0000000000000000000000000000000000000000..23c5d230741bfdb247124e8aece21f3806c68649 GIT binary patch literal 1355 zcmdPU(D1Fv)zpZNDUQ{S(Y22@(6x-!)`-!AFf{EoG*W9^HQ_Rv_8^s7I$#nmich^J zSgB@>hK5f~4oxl6hTG&(lR=72nh2d?HDzS#bgoI()SzWJRvXtMIW(}QkjB;-AzK$* zQ%q0m9BUFui3U>BB=M;iq*5E07Yt+3SVX0LQr(3Vzfm<+(43>G#o()8Ze*foW};(a cY^-N!q+o7np=V%$;2G+f8o_y^DhDQ%09s~8MF0Q* literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-2 b/fuzz/seed/regexp/bug316338-2 new file mode 100644 index 0000000000000000000000000000000000000000..5468d06dc298a7ea31c2504efa649a3877277832 GIT binary patch literal 74 zcmdPU&~UCv*3{65jwz1SiqW-?Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#MLCdS4JhDHFyq!Kp( literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-3 b/fuzz/seed/regexp/bug316338-3 new file mode 100644 index 0000000000000000000000000000000000000000..76e1e0bc37130e7f2a24ab3282f939e7f9ff1f45 GIT binary patch literal 75 zcmdPU&~UCv*3{65jwz1SiqW-?Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#MLCdS4JhDOE!*A5bD literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-4 b/fuzz/seed/regexp/bug316338-4 new file mode 100644 index 0000000000000000000000000000000000000000..e0f65a422d5e0b7eb51bbe15e1090981efa84c5d GIT binary patch literal 79 zcmdPU&~UCv*3{65jwz1SiqW-?Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#MLCdS4JhDOE;CZ=WpB7qYr literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-5 b/fuzz/seed/regexp/bug316338-5 new file mode 100644 index 0000000000000000000000000000000000000000..fcfaa97a11ff15c424a223d8048a6844b0f65975 GIT binary patch literal 487 zcmdPU&~UCv*3{65jwz1SiqW-?Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#ML=0+xZW+pl&#>RSvMhfPJ7J3F22%e#ysS%tvs&ZgL2>{z>VCDb- literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug316338-6 b/fuzz/seed/regexp/bug316338-6 new file mode 100644 index 0000000000000000000000000000000000000000..ce00a15bb2d87cb3443371f894f380bc1cd542b5 GIT binary patch literal 71 zcmdPU&~UCv*3{65jwz1Sj?uM`Hqf<<)z*m7gD^DhH8fIdTs7e`n)aI2#9p28IAn-38D9 literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug420596-2 b/fuzz/seed/regexp/bug420596-2 new file mode 100644 index 0000000000000000000000000000000000000000..474d2b6e4315164f731d8f0790412e1b89404d1c GIT binary patch literal 25 ecmdOh(XP?e)G&xP(6x-MF$7YEv6>9J28IAn;|09ph6Vsn-UZMA literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/bug420596-4 b/fuzz/seed/regexp/bug420596-4 new file mode 100644 index 0000000000000000000000000000000000000000..65d561eaebafd154aef08b1c1b3ba641b54b23cf GIT binary patch literal 25 ecmdOh(XP?e)G&xP(6x-MF$7YEv6>9Jh6VsnPx# literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/content-2 b/fuzz/seed/regexp/content-2 new file mode 100644 index 0000000000000000000000000000000000000000..4e6b663ea0ceb4e554f3c34914e8b446f1ad343a GIT binary patch literal 17 WcmdPUNUTY!N!CnBP19sZ0+IkQr3HZi literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/content-3 b/fuzz/seed/regexp/content-3 new file mode 100644 index 0000000000000000000000000000000000000000..b13fc8dbeaa96a2b0d5d096633004002d5dfb3e2 GIT binary patch literal 18 XcmdPUNUTY!N!CnBP19sZ1d{0hHi!l1 literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/content-4 b/fuzz/seed/regexp/content-4 new file mode 100644 index 0000000000000000000000000000000000000000..47c5d6de6ce9f84da3e626982e3e3adfaa9fda9b GIT binary patch literal 17 YcmdPUNUTY!N!CnBP19sZOiWD!05F&ZeEk literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ncname-3 b/fuzz/seed/regexp/ncname-3 new file mode 100644 index 0000000000000000000000000000000000000000..07a6a0818341fed0d59dfb30c02c265f3c2bb4c6 GIT binary patch literal 23 acma!!$<&Ruij9qqNe0te42em}hA9A7dj}W* literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ncname-4 b/fuzz/seed/regexp/ncname-4 new file mode 100644 index 0000000000000000000000000000000000000000..87e937f409e4e9392633f53621e3562c7868c617 GIT binary patch literal 21 Ycma!!$<&Ruij9qqNe0te42Frx07)GNQUCw| literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ncname-5 b/fuzz/seed/regexp/ncname-5 new file mode 100644 index 0000000000000000000000000000000000000000..ad294560904266700f0867053125df0089220462 GIT binary patch literal 23 acma!!$<&Ruij9qqNe0te42gzGR>=TX#Rl#G literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-1 b/fuzz/seed/regexp/ranges-1 new file mode 100644 index 0000000000000000000000000000000000000000..71448f2396913a83b220368d2dd992bbbdbb9257 GIT binary patch literal 8 PcmYeSHqtS!Wk>`73mF1T literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-10 b/fuzz/seed/regexp/ranges-10 new file mode 100644 index 0000000000000000000000000000000000000000..91aed3cf5a584fc4ae3a22feb4ee3954f3a4dc39 GIT binary patch literal 18 ZcmYe)NUBNJtTxgyu1#S`OioTt0RT2c1`902D(5ZvX%Q literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-5 b/fuzz/seed/regexp/ranges-5 new file mode 100644 index 0000000000000000000000000000000000000000..83ad4a82a7175ff067a8f9fdd84d4589bd1045d2 GIT binary patch literal 12 TcmYdFtTxgyu1#i0N=ya-8B7D# literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-6 b/fuzz/seed/regexp/ranges-6 new file mode 100644 index 0000000000000000000000000000000000000000..3bc9758f9a88096d176afb1e625c38dea90a3dad GIT binary patch literal 13 UcmYdFtTxgyu1#i0N=!@!03Cq@Hvj+t literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-7 b/fuzz/seed/regexp/ranges-7 new file mode 100644 index 0000000000000000000000000000000000000000..fa8903840b38d06e7203d6dad8e7f4ad3be18323 GIT binary patch literal 14 VcmYdFtTxgyu1#i0N=!^l1^^-#1egE- literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-8 b/fuzz/seed/regexp/ranges-8 new file mode 100644 index 0000000000000000000000000000000000000000..96f0bb690f24e43ffbcb289a6a6ffdf508703d23 GIT binary patch literal 15 UcmYdFtTxgyu1#i0N(6#r04ELv`2YX_ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges-9 b/fuzz/seed/regexp/ranges-9 new file mode 100644 index 0000000000000000000000000000000000000000..8e3fc43a4eaa0aeceedcf240bd5278a5df8db550 GIT binary patch literal 17 YcmYe)NUBNJtTxgyu1#S`OiE4x05Ed}YXATM literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges2-1 b/fuzz/seed/regexp/ranges2-1 new file mode 100644 index 0000000000000000000000000000000000000000..044a8eb93354c61a57fac6b1ecceb6232091d6d4 GIT binary patch literal 17 WcmdN$tVyai&@ryn1d@ie42b|QYy|!Q literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges2-10 b/fuzz/seed/regexp/ranges2-10 new file mode 100644 index 0000000000000000000000000000000000000000..19e2aa2db073df0e7d43ff9bb5c0bd5984c4dd54 GIT binary patch literal 42 gcmdOhHqf<(^b literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges2-7 b/fuzz/seed/regexp/ranges2-7 new file mode 100644 index 0000000000000000000000000000000000000000..74fbafb4e2149af7b61f8e53504a583fcea9dac7 GIT binary patch literal 18 XcmdN$tVyai&@ryn1d@ie42ekqG|UBH literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges2-8 b/fuzz/seed/regexp/ranges2-8 new file mode 100644 index 0000000000000000000000000000000000000000..125bfa91fcaf982516b4f36f4ae9352c525a962a GIT binary patch literal 18 XcmdN$tVyai&@ryn1d@ie3`vOqG|dHI literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/ranges2-9 b/fuzz/seed/regexp/ranges2-9 new file mode 100644 index 0000000000000000000000000000000000000000..f2cf128831dcc02e1566de8470b33630b7615373 GIT binary patch literal 41 fcmdOhHqf<_<% literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-1 b/fuzz/seed/regexp/xpath-1 new file mode 100644 index 0000000000000000000000000000000000000000..3bc17926cc6a2377c5ce52a800cb9cbdaf61dd8f GIT binary patch literal 181 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r JSyPK45da#=FW~?H literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-10 b/fuzz/seed/regexp/xpath-10 new file mode 100644 index 0000000000000000000000000000000000000000..e4f4b0cdde3e1429cdd34be5ac70329f196937eb GIT binary patch literal 212 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r dSyPJv>e57gC?m;At0qxjOFyXw=$AyRBmj!_Ig$VX literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-11 b/fuzz/seed/regexp/xpath-11 new file mode 100644 index 0000000000000000000000000000000000000000..318e0ccf39b4597f6106205b1475d157a666f64b GIT binary patch literal 181 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r JSyPL_5C9sPFR=gs literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-12 b/fuzz/seed/regexp/xpath-12 new file mode 100644 index 0000000000000000000000000000000000000000..f204295b26def133263018c368ddb44f0cda4b73 GIT binary patch literal 183 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r LSyPL_Ffj=Ldmk`# literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-13 b/fuzz/seed/regexp/xpath-13 new file mode 100644 index 0000000000000000000000000000000000000000..70fccd5917530d5b7bce8c45dac6e4fb51a00f25 GIT binary patch literal 183 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r LSyPK4(aI12doVCe literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-14 b/fuzz/seed/regexp/xpath-14 new file mode 100644 index 0000000000000000000000000000000000000000..357ce2b5627e43a1ce516d44736b64f6b3e8d5c4 GIT binary patch literal 182 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r KSyPL_ArSyd$uJ=R literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-15 b/fuzz/seed/regexp/xpath-15 new file mode 100644 index 0000000000000000000000000000000000000000..2a10a837029628f05f0f3a0d79f8dc4beefc5e2d GIT binary patch literal 191 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r TSyPK4F)ul_xFo;G$|?~65A!p$ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-16 b/fuzz/seed/regexp/xpath-16 new file mode 100644 index 0000000000000000000000000000000000000000..1f3089fb974c72cb5b2d224084e6b74c67c37cb1 GIT binary patch literal 181 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r JSyPKa82}oKFQWhe literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-17 b/fuzz/seed/regexp/xpath-17 new file mode 100644 index 0000000000000000000000000000000000000000..a9d542fb6f1bac51a19340d0748d4c585b6af903 GIT binary patch literal 241 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r zSyPKaS)n8&RiU6LwJbBgv{<1iH9fVWKq0LtKNl%nmS3a*W0wQ@Nk#eD Gsd)h9QboJ~ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-18 b/fuzz/seed/regexp/xpath-18 new file mode 100644 index 0000000000000000000000000000000000000000..651eb9d4c3a8c7cf3768564c915df70e94b99156 GIT binary patch literal 204 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r gSyPKaSs^2}C{-b|SfL~%RUs|2A~i)JKQGk^0Kg+RkN^Mx literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-19 b/fuzz/seed/regexp/xpath-19 new file mode 100644 index 0000000000000000000000000000000000000000..fefea8f1e6c1427d4b5924ff276ce75f48662f33 GIT binary patch literal 262 zcmcJ~u@1r@6op|Q#l+=al5$Cn3ybO6$p^TLA`ud38=&IA!)tv47q@TtbCLrriSP^n z#`$p9dNX@AV$&Cm1tK<<2=rTr0=U6{mQm~udsoV$iGt51%X*Y^deD$Q51uyDWxWM& isMgxOV(7AQHeNe3$7rXLsaL8WmNc#tDWy)*l^EX2#7pM@ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-2 b/fuzz/seed/regexp/xpath-2 new file mode 100644 index 0000000000000000000000000000000000000000..81e5fba0a9f4379db64f053ef9f49f61cbf5a06c GIT binary patch literal 241 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r QSyPK4(a=ag$(T$60QZYMwEzGB literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-20 b/fuzz/seed/regexp/xpath-20 new file mode 100644 index 0000000000000000000000000000000000000000..1f3089fb974c72cb5b2d224084e6b74c67c37cb1 GIT binary patch literal 181 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r JSyPKa82}oKFQWhe literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-21 b/fuzz/seed/regexp/xpath-21 new file mode 100644 index 0000000000000000000000000000000000000000..706a702576f19a885a3ab82ae18b822fb08133b3 GIT binary patch literal 277 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ S{hC@DF*O>4!zG$p42b|27)?4!zG$p42gzD`boxQ5&+tRTO|Mh literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-23 b/fuzz/seed/regexp/xpath-23 new file mode 100644 index 0000000000000000000000000000000000000000..02753beb3e4259cc7e3c189dc2eedbb3b653738b GIT binary patch literal 277 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ S{hC@DF*O>4!zG$p3|asd;Y}I< literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-24 b/fuzz/seed/regexp/xpath-24 new file mode 100644 index 0000000000000000000000000000000000000000..331105cdce1afab68181b909f6f26d22c4d531c5 GIT binary patch literal 279 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ U{hC@DF*O>4!zG$p42d;K0J9WMF8}}l literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-25 b/fuzz/seed/regexp/xpath-25 new file mode 100644 index 0000000000000000000000000000000000000000..ce3da4436759c625c60c974ce793b5f80de1dd77 GIT binary patch literal 282 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ X{hC@DF*O>4!zG$p48Racv`PX1oGMOv literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-26 b/fuzz/seed/regexp/xpath-26 new file mode 100644 index 0000000000000000000000000000000000000000..b3bf8c23dd7c8a7a695b2766b0c4f0bd58cb2fc2 GIT binary patch literal 281 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ W{hC@DF*O>4!zG$p42k+l`pE!K4o-9c literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-27 b/fuzz/seed/regexp/xpath-27 new file mode 100644 index 0000000000000000000000000000000000000000..74bbe4680aec8a5e6a3db318544bd59882a0c839 GIT binary patch literal 281 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ W{hC@DF*O>4!zG$p42k+$`bhvzWllQ) literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-28 b/fuzz/seed/regexp/xpath-28 new file mode 100644 index 0000000000000000000000000000000000000000..b38a709e791eecb2311f909fed936fa0661e8d9c GIT binary patch literal 287 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ b{hC@DF*O>4!zG$p42f1+`bj{XY^4PNDFjcT literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-29 b/fuzz/seed/regexp/xpath-29 new file mode 100644 index 0000000000000000000000000000000000000000..104d4e54a151ecd4ac683c0de6e38370a41cc6b1 GIT binary patch literal 295 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ a{hC@DF*O>4!zG$p4A78B)Q2*Xth4~aw^KF% literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-3 b/fuzz/seed/regexp/xpath-3 new file mode 100644 index 0000000000000000000000000000000000000000..6d7be85f2d0e027b15d0de87a10654ca6bdf1e19 GIT binary patch literal 181 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r JSyPKa3ji9DFRB0l literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-30 b/fuzz/seed/regexp/xpath-30 new file mode 100644 index 0000000000000000000000000000000000000000..b681ff14ac565bb3738c009418adb25ceecbd41f GIT binary patch literal 308 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ n{hC@DF*O>4!zG$p4A78B)Q2*Xth8zp^|kbqYJg#tXq5y27!X$i literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-31 b/fuzz/seed/regexp/xpath-31 new file mode 100644 index 0000000000000000000000000000000000000000..cd87b0e8d35abc93990fd3dd08eba75d97724a9d GIT binary patch literal 277 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ S{hC@DF*O>4!zG$p42A#}=uII2 literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-32 b/fuzz/seed/regexp/xpath-32 new file mode 100644 index 0000000000000000000000000000000000000000..c5cac32ab94e5e23d59464f53b74523b1ba05181 GIT binary patch literal 279 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ U{hC@DF*O>4!zG$p42FqG0J2U^4!zG$p42f2T0J2|AyZ`_I literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-34 b/fuzz/seed/regexp/xpath-34 new file mode 100644 index 0000000000000000000000000000000000000000..b65a3d6ff3a236698f4c73c9f4333450b84390f0 GIT binary patch literal 278 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ T{hC@DF*O>4!zG$p3=W9^WQa|X literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-35 b/fuzz/seed/regexp/xpath-35 new file mode 100644 index 0000000000000000000000000000000000000000..252a70c2eb2d608d31aa3185b350d9cfbb176d2d GIT binary patch literal 287 zcmdOh(bL!0wAawkNY2R2NwKm5v7=)$b)&6fW20k|!L$}g6hp8kMoUvuvnEDQQ$wFJ c{hC@DF*O>4!zG$p42gNksl_GvMOIdc05Y*rBme*a literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-4 b/fuzz/seed/regexp/xpath-4 new file mode 100644 index 0000000000000000000000000000000000000000..30718c579cb8cc03e1da1dfdb6762a7deee00cf0 GIT binary patch literal 183 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r LSyPK4u_g%sd*v{{ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-5 b/fuzz/seed/regexp/xpath-5 new file mode 100644 index 0000000000000000000000000000000000000000..06ad88ef4e896e02d15deabdb294cbba7583d5d5 GIT binary patch literal 186 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r NSyPJv=;B1HBmfMnF$n+w literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-6 b/fuzz/seed/regexp/xpath-6 new file mode 100644 index 0000000000000000000000000000000000000000..6678772837df9df7a510f560e5805a1a538fd796 GIT binary patch literal 185 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r NSyPK4Q9nsP835eyF$4er literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-7 b/fuzz/seed/regexp/xpath-7 new file mode 100644 index 0000000000000000000000000000000000000000..e69ad856f1191b24c687e23aad0fa4997020088f GIT binary patch literal 185 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r NSyPK4QC~|x2>{$jFv|b{ literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-8 b/fuzz/seed/regexp/xpath-8 new file mode 100644 index 0000000000000000000000000000000000000000..a8120ccdcc334581d0ebe369f854ab6346b9ff85 GIT binary patch literal 191 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r RSyPK4(Mn4{35b)ev;YQ1GB5xD literal 0 HcmV?d00001 diff --git a/fuzz/seed/regexp/xpath-9 b/fuzz/seed/regexp/xpath-9 new file mode 100644 index 0000000000000000000000000000000000000000..c037ce7fbd8d0ff91401e82430b7d454f0f65aaa GIT binary patch literal 199 zcmdOh(bL!0wAawkNY2R2NwKm5v12l0lC?lAFry|$OH)&`CPq(FL!UTxnpzq$H5#-r RSyPJv>e57gC?m;A3jnlgHO2q{ literal 0 HcmV?d00001 diff --git a/fuzz/seed/uri/dot b/fuzz/seed/uri/dot new file mode 100644 index 00000000..945c9b46 --- /dev/null +++ b/fuzz/seed/uri/dot @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/fuzz/seed/uri/full b/fuzz/seed/uri/full new file mode 100644 index 0000000000000000000000000000000000000000..808e58a1522ffbf3e6aeedf4086fc81864360f0c GIT binary patch literal 36 rcmc~ODJihh*Dtjya40v{%P&f|vM|su&@a?a(@V9_wk=amW6%Qt*aiyq literal 0 HcmV?d00001 diff --git a/fuzz/testFuzzer.c b/fuzz/testFuzzer.c new file mode 100644 index 00000000..f6be7b8f --- /dev/null +++ b/fuzz/testFuzzer.c @@ -0,0 +1,55 @@ +/* + * testFuzzer.c: Test program for the custom entity loader used to fuzz + * with multiple inputs. + * + * See Copyright for the status of this software. + */ + +#include +#include +#include +#include +#include "fuzz.h" + +int +main() { + static const char data[] = + "doc.xml\\\n" + "\n" + "&ent;\\\n" + "doc.dtd\\\n" + "\n" + "\\\n" + "ent.txt\\\n" + "Hello, world!\\\n"; + static xmlChar expected[] = + "\n" + "\n" + "Hello, world!\n"; + const char *docBuffer; + size_t docSize; + xmlDocPtr doc; + xmlChar *out; + int ret = 0; + + xmlSetExternalEntityLoader(xmlFuzzEntityLoader); + + xmlFuzzDataInit(data, sizeof(data) - 1); + xmlFuzzReadEntities(); + docBuffer = xmlFuzzMainEntity(&docSize); + doc = xmlReadMemory(docBuffer, docSize, NULL, NULL, + XML_PARSE_NOENT | XML_PARSE_DTDLOAD); + + xmlDocDumpMemory(doc, &out, NULL); + if (xmlStrcmp(out, expected) != 0) { + fprintf(stderr, "Expected:\n%sGot:\n%s", expected, out); + ret = 1; + } + + xmlFree(out); + xmlFreeDoc(doc); + xmlFuzzDataCleanup(); + + return(ret); +} + diff --git a/fuzz/uri.c b/fuzz/uri.c new file mode 100644 index 00000000..69d0439f --- /dev/null +++ b/fuzz/uri.c @@ -0,0 +1,45 @@ +/* + * uri.c: a libFuzzer target to test the URI module. + * + * See Copyright for the status of this software. + */ + +#include +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput(const char *data, size_t size) { + xmlURIPtr uri; + char *str[2] = { NULL, NULL }; + size_t numStrings; + + numStrings = xmlFuzzExtractStrings(data, size, str, 2); + + uri = xmlParseURI(str[0]); + xmlFree(xmlSaveUri(uri)); + xmlFreeURI(uri); + + uri = xmlParseURIRaw(str[0], 1); + xmlFree(xmlSaveUri(uri)); + xmlFreeURI(uri); + + xmlFree(xmlURIUnescapeString(str[0], -1, NULL)); + xmlFree(xmlURIEscape(BAD_CAST str[0])); + xmlFree(xmlCanonicPath(BAD_CAST str[0])); + xmlFree(xmlPathToURI(BAD_CAST str[0])); + + if (numStrings >= 2) { + xmlFree(xmlBuildURI(BAD_CAST str[1], BAD_CAST str[0])); + xmlFree(xmlBuildRelativeURI(BAD_CAST str[1], BAD_CAST str[0])); + xmlFree(xmlURIEscapeStr(BAD_CAST str[0], BAD_CAST str[1])); + } + + /* Modifies string, so must come last. */ + xmlNormalizeURIPath(str[0]); + + xmlFree(str[0]); + xmlFree(str[1]); + + return 0; +} + diff --git a/fuzz/xml.c b/fuzz/xml.c new file mode 100644 index 00000000..50dd967d --- /dev/null +++ b/fuzz/xml.c @@ -0,0 +1,90 @@ +/* + * xml.c: a libFuzzer target to test several XML parser interfaces. + * + * See Copyright for the status of this software. + */ + +#include +#include +#include +#include +#include "fuzz.h" + +int +LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED, + char ***argv ATTRIBUTE_UNUSED) { + xmlInitParser(); + xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc); + xmlSetExternalEntityLoader(xmlFuzzEntityLoader); + + return 0; +} + +int +LLVMFuzzerTestOneInput(const char *data, size_t size) { + static const size_t maxChunkSize = 128; + xmlDocPtr doc; + xmlParserCtxtPtr ctxt; + xmlTextReaderPtr reader; + xmlChar *out; + const char *docBuffer; + size_t docSize, consumed, chunkSize; + int opts, outSize; + + xmlFuzzDataInit(data, size); + opts = xmlFuzzReadInt(); + /* XML_PARSE_HUGE still causes timeouts. */ + opts &= ~XML_PARSE_HUGE; + + xmlFuzzReadEntities(); + docBuffer = xmlFuzzMainEntity(&docSize); + if (docBuffer == NULL) { + xmlFuzzDataCleanup(); + return(0); + } + + /* Pull parser */ + + doc = xmlReadMemory(docBuffer, docSize, NULL, NULL, opts); + /* Also test the serializer. */ + xmlDocDumpMemory(doc, &out, &outSize); + xmlFree(out); + xmlFreeDoc(doc); + + /* Push parser */ + + ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL); + xmlCtxtUseOptions(ctxt, opts); + + for (consumed = 0; consumed < docSize; consumed += chunkSize) { + chunkSize = docSize - consumed; + if (chunkSize > maxChunkSize) + chunkSize = maxChunkSize; + xmlParseChunk(ctxt, docBuffer + consumed, chunkSize, 0); + } + + xmlParseChunk(ctxt, NULL, 0, 1); + xmlFreeDoc(ctxt->myDoc); + xmlFreeParserCtxt(ctxt); + + /* Reader */ + + reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts); + while (xmlTextReaderRead(reader) == 1) { + if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) { + int i, n = xmlTextReaderAttributeCount(reader); + for (i=0; i +#include +#include +#include +#include +#include +#include +#include "fuzz.h" + +static xmlHashTablePtr entities; + +static void +errorFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED, ...) { + /* Discard error messages. */ +} + +/* + * Write a random-length string in a format similar to FuzzedDataProvider. + * Backslash followed by newline marks the end of the string. Two + * backslashes are used to escape a backslash. + */ +static void +writeEscaped(const char *str) { + for (; *str; str++) { + int c = (unsigned char) *str; + putchar(c); + if (c == '\\') + putchar(c); + } + putchar('\\'); + putchar('\n'); +} + +/* + * A custom entity loader that writes all external DTDs or entities to a + * single file in the format expected by xmlFuzzEntityLoader. + */ +static xmlParserInputPtr +entityLoader(const char *URL, const char *ID, xmlParserCtxtPtr context) { + xmlParserInputPtr in; + static const int chunkSize = 16384; + int len; + + in = xmlNoNetExternalEntityLoader(URL, ID, context); + if (in == NULL) + return(NULL); + + if (xmlHashLookup(entities, (const xmlChar *) URL) != NULL) + return(in); + + do { + len = xmlParserInputBufferGrow(in->buf, chunkSize); + if (len < 0) { + fprintf(stderr, "Error reading %s\n", URL); + xmlFreeInputStream(in); + return(NULL); + } + } while (len > 0); + + writeEscaped(URL); + writeEscaped((char *) xmlBufContent(in->buf->buffer)); + + xmlFreeInputStream(in); + + xmlHashAddEntry(entities, (const xmlChar *) URL, "seen"); + + return(xmlNoNetExternalEntityLoader(URL, ID, context)); +} + +int +main(int argc, char **argv) { + int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD; + + if (argc != 2) { + fprintf(stderr, "Usage: xmlSeed [FILE]\n"); + } + + fwrite(&opts, sizeof(opts), 1, stdout); + + entities = xmlHashCreate(4); + xmlSetGenericErrorFunc(NULL, errorFunc); + xmlSetExternalEntityLoader(entityLoader); + xmlFreeDoc(xmlReadFile(argv[1], NULL, opts)); + xmlHashFree(entities, NULL); + + return(0); +} +