From 0542b1869b6970003caa954ebc5f1dea41d48032 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 12 Mar 2015 20:21:59 -0700 Subject: Fix buffer overrun when parsing comments inside DOCTYPE --- src/pugixml.cpp | 2 +- tests/test_parse.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/pugixml.cpp b/src/pugixml.cpp index ce8a79f..4269335 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -2352,7 +2352,7 @@ PUGI__NS_BEGIN PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - s += 4; + s += 3; } else PUGI__THROW_ERROR(status_bad_doctype, s); diff --git a/tests/test_parse.cpp b/tests/test_parse.cpp index 1b1e807..7bb2663 100644 --- a/tests/test_parse.cpp +++ b/tests/test_parse.cpp @@ -1091,3 +1091,17 @@ TEST(parse_close_tag_eof) CHECK(doc.load_buffer_inplace(test2, 12 * sizeof(char_t)).status == status_end_element_mismatch); CHECK_STRING(doc.first_child().name(), STR("node")); } + +TEST(parse_fuzz_doctype) +{ + unsigned char data[] = + { + 0x3b, 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0xef, 0xbb, 0xbf, 0x3c, 0x3f, 0x78, + 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, + 0x3f, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0xe9, 0x80, 0xb1, 0xe5, 0xa0, 0xb1, 0xe3, 0x82, 0xb4, + 0xe3, 0x83, 0xb3, 0x20, 0xef, 0x83, 0x97, 0xe3, 0xa9, 0x2a, 0x20, 0x2d, 0x2d, 0x3e + }; + + xml_document doc; + CHECK(doc.load_buffer(data, sizeof(data)).status == status_bad_doctype); +} -- cgit v1.2.3 From 15fba1debca5498989048677ffda38758b2df984 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Fri, 13 Mar 2015 00:18:30 -0700 Subject: tests: Add support for afl-fuzz With the current setup it successfully finds the (fixed) DOCTYPE buffer overrun in ~50 minutes (on a single core). --- Makefile | 11 ++++++++--- tests/data_fuzz_parse/basic.xml | 1 + tests/data_fuzz_parse/doctype.xml | 1 + tests/data_fuzz_parse/refs.xml | 1 + tests/data_fuzz_parse/types.xml | 1 + tests/data_fuzz_parse/utf16.xml | Bin 0 -> 700 bytes tests/data_fuzz_parse/utf32.xml | Bin 0 -> 652 bytes tests/fuzz_parse.cpp | 16 ++++++++++++++++ 8 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/data_fuzz_parse/basic.xml create mode 100644 tests/data_fuzz_parse/doctype.xml create mode 100644 tests/data_fuzz_parse/refs.xml create mode 100644 tests/data_fuzz_parse/types.xml create mode 100644 tests/data_fuzz_parse/utf16.xml create mode 100644 tests/data_fuzz_parse/utf32.xml create mode 100644 tests/fuzz_parse.cpp diff --git a/Makefile b/Makefile index 897bcbb..b50ff69 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,10 @@ defines=standard BUILD=build/make-$(CXX)-$(config)-$(defines) -SOURCES=src/pugixml.cpp $(wildcard tests/*.cpp) +SOURCES=src/pugixml.cpp tests/main.cpp tests/allocator.cpp tests/test.cpp tests/writer_string.cpp $(wildcard tests/test_*.cpp) EXECUTABLE=$(BUILD)/test -CXXFLAGS=-c -g -Wall -Wextra -Werror -pedantic +CXXFLAGS=-g -Wall -Wextra -Werror -pedantic LDFLAGS= ifeq ($(config),release) @@ -39,6 +39,11 @@ 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 @@ + clean: rm -rf $(BUILD) @@ -47,7 +52,7 @@ $(EXECUTABLE): $(OBJECTS) $(BUILD)/%.o: % @mkdir -p $(dir $@) - $(CXX) $< $(CXXFLAGS) -MMD -MP -o $@ + $(CXX) $< $(CXXFLAGS) -c -MMD -MP -o $@ -include $(OBJECTS:.o=.d) diff --git a/tests/data_fuzz_parse/basic.xml b/tests/data_fuzz_parse/basic.xml new file mode 100644 index 0000000..a8eaa09 --- /dev/null +++ b/tests/data_fuzz_parse/basic.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/data_fuzz_parse/doctype.xml b/tests/data_fuzz_parse/doctype.xml new file mode 100644 index 0000000..dd1831d --- /dev/null +++ b/tests/data_fuzz_parse/doctype.xml @@ -0,0 +1 @@ + ]> ]]> ]> ]> \ No newline at end of file diff --git a/tests/data_fuzz_parse/refs.xml b/tests/data_fuzz_parse/refs.xml new file mode 100644 index 0000000..e42df5f --- /dev/null +++ b/tests/data_fuzz_parse/refs.xml @@ -0,0 +1 @@ + pcdata < > & " ' « &unknown; %entity; \ No newline at end of file diff --git a/tests/data_fuzz_parse/types.xml b/tests/data_fuzz_parse/types.xml new file mode 100644 index 0000000..dc6369a --- /dev/null +++ b/tests/data_fuzz_parse/types.xml @@ -0,0 +1 @@ + pcdata \ No newline at end of file diff --git a/tests/data_fuzz_parse/utf16.xml b/tests/data_fuzz_parse/utf16.xml new file mode 100644 index 0000000..3847a93 Binary files /dev/null and b/tests/data_fuzz_parse/utf16.xml differ diff --git a/tests/data_fuzz_parse/utf32.xml b/tests/data_fuzz_parse/utf32.xml new file mode 100644 index 0000000..51b8a89 Binary files /dev/null and b/tests/data_fuzz_parse/utf32.xml differ diff --git a/tests/fuzz_parse.cpp b/tests/fuzz_parse.cpp new file mode 100644 index 0000000..e758196 --- /dev/null +++ b/tests/fuzz_parse.cpp @@ -0,0 +1,16 @@ +#include "../src/pugixml.hpp" +#include "allocator.hpp" + +int main(int argc, const char** argv) +{ + pugi::set_memory_management_functions(memory_allocate, memory_deallocate); + + 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); + } +} -- cgit v1.2.3