diff options
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | tests/data_fuzz_xpath/basic.xpath | 1 | ||||
-rw-r--r-- | tests/data_fuzz_xpath/functions.xpath | 1 | ||||
-rw-r--r-- | tests/data_fuzz_xpath/math.xpath | 1 | ||||
-rw-r--r-- | tests/data_fuzz_xpath/path.xpath | 1 | ||||
-rw-r--r-- | tests/data_fuzz_xpath/predicate.xpath | 1 | ||||
-rw-r--r-- | tests/fuzz_parse.cpp | 18 | ||||
-rw-r--r-- | tests/fuzz_parse.dict | 72 | ||||
-rwxr-xr-x | tests/fuzz_setup.sh | 13 | ||||
-rw-r--r-- | tests/fuzz_xpath.cpp | 26 | ||||
-rw-r--r-- | tests/fuzz_xpath.dict | 72 |
11 files changed, 203 insertions, 14 deletions
@@ -68,10 +68,9 @@ test: $(EXECUTABLE) ./$(EXECUTABLE) endif -fuzz: - @mkdir -p $(BUILD) - $(AFL)/afl-clang++ tests/fuzz_parse.cpp tests/allocator.cpp src/pugixml.cpp $(CXXFLAGS) -o $(BUILD)/fuzz_parse - $(AFL)/afl-fuzz -i tests/data_fuzz_parse -o $(BUILD)/fuzz_parse_out -x $(AFL)/testcases/_extras/xml/ -- $(BUILD)/fuzz_parse @@ +fuzz_%: $(BUILD)/fuzz_% + @mkdir -p build/$@ + $< build/$@ tests/data_$* -max_len=1024 -dict=tests/fuzz_$*.dict clean: rm -rf $(BUILD) @@ -87,6 +86,10 @@ build/pugixml-%: .FORCE | $(RELEASE) $(EXECUTABLE): $(OBJECTS) $(CXX) $(OBJECTS) $(LDFLAGS) -o $@ +$(BUILD)/fuzz_%: tests/fuzz_%.cpp src/pugixml.cpp + @mkdir -p $(BUILD) + clang++ $(CXXFLAGS) -fsanitize=address -fsanitize-coverage=trace-pc-guard $^ libFuzzer.a -o $@ + $(BUILD)/%.o: % @mkdir -p $(dir $@) $(CXX) $< $(CXXFLAGS) -c -MMD -MP -o $@ diff --git a/tests/data_fuzz_xpath/basic.xpath b/tests/data_fuzz_xpath/basic.xpath new file mode 100644 index 0000000..ccbaf23 --- /dev/null +++ b/tests/data_fuzz_xpath/basic.xpath @@ -0,0 +1 @@ +a/b/c
\ No newline at end of file diff --git a/tests/data_fuzz_xpath/functions.xpath b/tests/data_fuzz_xpath/functions.xpath new file mode 100644 index 0000000..ec24b4f --- /dev/null +++ b/tests/data_fuzz_xpath/functions.xpath @@ -0,0 +1 @@ +sum(nodes) + round(concat(//a[translate(@id, 'abc', '012')]))
diff --git a/tests/data_fuzz_xpath/math.xpath b/tests/data_fuzz_xpath/math.xpath new file mode 100644 index 0000000..7f6e968 --- /dev/null +++ b/tests/data_fuzz_xpath/math.xpath @@ -0,0 +1 @@ +1+2*3 div 4 mod 5-6
\ No newline at end of file diff --git a/tests/data_fuzz_xpath/path.xpath b/tests/data_fuzz_xpath/path.xpath new file mode 100644 index 0000000..82cace9 --- /dev/null +++ b/tests/data_fuzz_xpath/path.xpath @@ -0,0 +1 @@ +@*/ancestor::*/near-north/*[4]/@*/preceding::text()
\ No newline at end of file diff --git a/tests/data_fuzz_xpath/predicate.xpath b/tests/data_fuzz_xpath/predicate.xpath new file mode 100644 index 0000000..7161d55 --- /dev/null +++ b/tests/data_fuzz_xpath/predicate.xpath @@ -0,0 +1 @@ +library/nodes[@id=12]/element[@type='translate'][1]
\ No newline at end of file diff --git a/tests/fuzz_parse.cpp b/tests/fuzz_parse.cpp index e758196..94c610a 100644 --- a/tests/fuzz_parse.cpp +++ b/tests/fuzz_parse.cpp @@ -1,16 +1,14 @@ #include "../src/pugixml.hpp" -#include "allocator.hpp" -int main(int argc, const char** argv) -{ - pugi::set_memory_management_functions(memory_allocate, memory_deallocate); +#include <stdint.h> +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ pugi::xml_document doc; - for (int i = 1; i < argc; ++i) - { - doc.load_file(argv[i]); - doc.load_file(argv[i], pugi::parse_minimal); - doc.load_file(argv[i], pugi::parse_full); - } + doc.load_buffer(Data, Size); + doc.load_buffer(Data, Size, pugi::parse_minimal); + doc.load_buffer(Data, Size, pugi::parse_full); + + return 0; } diff --git a/tests/fuzz_parse.dict b/tests/fuzz_parse.dict new file mode 100644 index 0000000..b1a0067 --- /dev/null +++ b/tests/fuzz_parse.dict @@ -0,0 +1,72 @@ +#
+# AFL dictionary for XML
+# ----------------------
+#
+# Several basic syntax elements and attributes, modeled on libxml2.
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+attr_encoding=" encoding=\"1\""
+attr_generic=" a=\"1\""
+attr_href=" href=\"1\""
+attr_standalone=" standalone=\"no\""
+attr_version=" version=\"1\""
+attr_xml_base=" xml:base=\"1\""
+attr_xml_id=" xml:id=\"1\""
+attr_xml_lang=" xml:lang=\"1\""
+attr_xml_space=" xml:space=\"1\""
+attr_xmlns=" xmlns=\"1\""
+
+entity_builtin="<"
+entity_decimal=""
+entity_external="&a;"
+entity_hex=""
+
+string_any="ANY"
+string_brackets="[]"
+string_cdata="CDATA"
+string_col_fallback=":fallback"
+string_col_generic=":a"
+string_col_include=":include"
+string_dashes="--"
+string_empty="EMPTY"
+string_empty_dblquotes="\"\""
+string_empty_quotes="''"
+string_entities="ENTITIES"
+string_entity="ENTITY"
+string_fixed="#FIXED"
+string_id="ID"
+string_idref="IDREF"
+string_idrefs="IDREFS"
+string_implied="#IMPLIED"
+string_nmtoken="NMTOKEN"
+string_nmtokens="NMTOKENS"
+string_notation="NOTATION"
+string_parentheses="()"
+string_pcdata="#PCDATA"
+string_percent="%a"
+string_public="PUBLIC"
+string_required="#REQUIRED"
+string_schema=":schema"
+string_system="SYSTEM"
+string_ucs4="UCS-4"
+string_utf16="UTF-16"
+string_utf8="UTF-8"
+string_xmlns="xmlns:"
+
+tag_attlist="<!ATTLIST"
+tag_cdata="<![CDATA["
+tag_close="</a>"
+tag_doctype="<!DOCTYPE"
+tag_element="<!ELEMENT"
+tag_entity="<!ENTITY"
+tag_ignore="<![IGNORE["
+tag_include="<![INCLUDE["
+tag_notation="<!NOTATION"
+tag_open="<a>"
+tag_open_close="<a />"
+tag_open_exclamation="<!"
+tag_open_q="<?"
+tag_sq2_close="]]>"
+tag_xml_q="<?xml?>"
diff --git a/tests/fuzz_setup.sh b/tests/fuzz_setup.sh new file mode 100755 index 0000000..05a40cb --- /dev/null +++ b/tests/fuzz_setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +sudo apt-get --yes install subversion screen gcc g++ cmake ninja-build golang autoconf libtool apache2 python-dev pkg-config zlib1g-dev libgcrypt11-dev + +cd clang +git clone https://chromium.googlesource.com/chromium/src/tools/clang +cd .. +clang/clang/scripts/update.py +sudo cp -rf third_party/llvm-build/Release+Asserts/lib/* /usr/local/lib/ +sudo cp -rf third_party/llvm-build/Release+Asserts/bin/* /usr/local/bin + +svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer +Fuzzer/build.sh diff --git a/tests/fuzz_xpath.cpp b/tests/fuzz_xpath.cpp new file mode 100644 index 0000000..c7ff4cd --- /dev/null +++ b/tests/fuzz_xpath.cpp @@ -0,0 +1,26 @@ +#include "../src/pugixml.hpp" + +#include <stdint.h> +#include <string.h> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ + char* text = new char[Size + 1]; + memcpy(text, Data, Size); + text[Size] = 0; + +#ifdef PUGIXML_NO_EXCEPTIONS + pugi::xpath_query q(text); +#else + try + { + pugi::xpath_query q(text); + } + catch (pugi::xpath_exception&) + { + } +#endif + + delete[] text; + return 0; +} diff --git a/tests/fuzz_xpath.dict b/tests/fuzz_xpath.dict new file mode 100644 index 0000000..c469f6e --- /dev/null +++ b/tests/fuzz_xpath.dict @@ -0,0 +1,72 @@ +"boolean"
+"count"
+"contains"
+"concat"
+"ceiling"
+"false"
+"floor"
+"id"
+"last"
+"lang"
+"local-name"
+"name"
+"namespace-uri"
+"normalize-space"
+"not"
+"number"
+"position"
+"round"
+"string"
+"string-length"
+"starts-with"
+"substring-before"
+"substring-after"
+"substring"
+"sum"
+"translate"
+"true"
+"ancestor"
+"ancestor-or-self"
+"attribute"
+"child"
+"descendant"
+"descendant-or-self"
+"following"
+"following-sibling"
+"namespace"
+"parent"
+"preceding"
+"preceding-sibling"
+"self"
+"comment"
+"node"
+"processing-instruction"
+"text"
+"or"
+"and"
+"div"
+"mod"
+">"
+">="
+"<"
+"<="
+"!"
+"!="
+"="
+"+"
+"-"
+"*"
+"|"
+"$"
+"("
+")"
+"["
+"]"
+","
+"//"
+"/"
+".."
+"."
+"@"
+"::"
+":"
|