Skip to content

Commit 0175f1a

Browse files
authored
poco: XML parsers fuzzing (#12214)
New fuzzing target for Poco::XML library: DOMParser, SAXParser and XMLStreamParser.
1 parent e0d3b99 commit 0175f1a

File tree

4 files changed

+221
-0
lines changed

4 files changed

+221
-0
lines changed

projects/poco/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ RUN git clone --depth 1 https://github.com/pocoproject/poco
2121
WORKDIR $SRC/poco
2222
COPY build.sh \
2323
json_parse_fuzzer.cc \
24+
xml_parse_fuzzer.cc \
25+
xml.dict \
2426
$SRC/

projects/poco/build.sh

+15
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,18 @@ $CXX $CXXFLAGS $LIB_FUZZING_ENGINE json_fuzzer.o \
3535
./lib/libPocoJSON.a \
3636
./lib/libPocoFoundation.a \
3737
-o $OUT/json_parser_fuzzer -lpthread -ldl -lrt
38+
39+
$CXX $CXXFLAGS -DPOCO_HAVE_FD_EPOLL -DPOCO_OS_FAMILY_UNIX \
40+
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \
41+
-D_REENTRANT -D_THREAD_SAFE -D_XOPEN_SOURCE=500 \
42+
-I/src/poco/XML/include \
43+
-I/src/poco/Foundation/include \
44+
-O2 -g -DNDEBUG -std=c++17 \
45+
-o xml_fuzzer.o -c $SRC/xml_parse_fuzzer.cc
46+
47+
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE xml_fuzzer.o \
48+
./lib/libPocoXML.a \
49+
./lib/libPocoFoundation.a \
50+
-o $OUT/xml_parser_fuzzer -lpthread -ldl -lrt
51+
52+
cp $SRC/xml.dict $OUT/xml_parser_fuzzer.dict

projects/poco/xml.dict

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
attr_encoding=" encoding=\"1\""
2+
attr_generic=" a=\"1\""
3+
attr_href=" href=\"1\""
4+
attr_standalone=" standalone=\"no\""
5+
attr_version=" version=\"1\""
6+
attr_xml_base=" xml:base=\"1\""
7+
attr_xml_id=" xml:id=\"1\""
8+
attr_xml_lang=" xml:lang=\"1\""
9+
attr_xml_space=" xml:space=\"1\""
10+
attr_xmlns=" xmlns=\"1\""
11+
12+
entity_builtin="<"
13+
entity_decimal=""
14+
entity_external="&a;"
15+
entity_hex=""
16+
17+
# keywords
18+
"ANY"
19+
"ATTLIST"
20+
"CDATA"
21+
"DOCTYPE"
22+
"ELEMENT"
23+
"EMPTY"
24+
"ENTITIES"
25+
"ENTITY"
26+
"FIXED"
27+
"ID"
28+
"IDREF"
29+
"IDREFS"
30+
"IGNORE"
31+
"IMPLIED"
32+
"INCLUDE"
33+
"NDATA"
34+
"NMTOKEN"
35+
"NMTOKENS"
36+
"NOTATION"
37+
"PCDATA"
38+
"PUBLIC"
39+
"REQUIRED"
40+
"SYSTEM"
41+
42+
# Various tag parts
43+
"<"
44+
">"
45+
"/>"
46+
"</"
47+
"<?"
48+
"?>"
49+
"<!"
50+
"!>"
51+
"[]"
52+
"]]"
53+
"<![CDATA["
54+
"<![CDATA[]]>"
55+
"\"\""
56+
"''"
57+
"=\"\""
58+
"=''"
59+
60+
# DTD
61+
"<!ATTLIST"
62+
"<!DOCTYPE"
63+
"<!ELEMENT"
64+
"<!ENTITY"
65+
"<![IGNORE["
66+
"<![INCLUDE["
67+
"<!NOTATION"
68+
"#CDATA"
69+
"#FIXED"
70+
"#IMPLIED"
71+
"#PCDATA"
72+
"#REQUIRED"
73+
74+
# Encodings
75+
"ISO-8859-1"
76+
"US-ASCII"
77+
"UTF-8"
78+
"UTF-16"
79+
"UTF-16BE"
80+
"UTF-16LE"
81+
82+
# Namespaces and schemas
83+
"xmlns"
84+
"xmlns:"
85+
"xmlns:xhtml=\"http://www.w3.org/1999/xhtml\""
86+
"xmlns:xml=\"http://www.w3.org/XML/1998/namespace\""
87+
"xmlns:xmlns=\"http://www.w3.org/2000/xmlns\""
88+
89+
string_col_fallback=":fallback"
90+
string_col_generic=":a"
91+
string_col_include=":include"
92+
string_dashes="--"
93+
string_parentheses="()"
94+
string_percent="%a"
95+
string_schema=":schema"
96+
string_ucs4="UCS-4"
97+
tag_close="</a>"
98+
tag_open="<a>"
99+
tag_open_close="<a />"
100+
101+
102+
"<?xml?>"
103+
"http://docboo"
104+
"http://www.w"
105+
"he30"
106+
"he2"
107+
"IET"
108+
"FDF-10"
109+
"aDUCS-4OPveb:"
110+
"a>"
111+
"UT"
112+
"xMl"
113+
"/usr/share/sg"
114+
"ha07"
115+
"http://www.oa"
116+
"cle"

projects/poco/xml_parse_fuzzer.cc

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "Poco/AutoPtr.h"
16+
#include "Poco/DOM/DOMParser.h"
17+
#include "Poco/DOM/Document.h"
18+
#include "Poco/SAX/DefaultHandler.h"
19+
#include "Poco/SAX/SAXParser.h"
20+
#include "Poco/XML/XMLStreamParser.h"
21+
22+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
23+
using namespace Poco::XML;
24+
25+
std::string xml(reinterpret_cast<const char *>(data), size);
26+
27+
// SAX Parser
28+
29+
SAXParser saxParser;
30+
std::uint8_t saxFeatures = size > 0 ? data[size - 1] : 0;
31+
32+
DefaultHandler defHandler;
33+
saxParser.setContentHandler(&defHandler);
34+
saxParser.setDTDHandler(&defHandler);
35+
saxParser.setErrorHandler(&defHandler);
36+
saxParser.setEntityResolver(&defHandler);
37+
38+
for (const auto feature : {
39+
XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES,
40+
XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES,
41+
XMLReader::FEATURE_NAMESPACES,
42+
XMLReader::FEATURE_NAMESPACE_PREFIXES,
43+
SAXParser::FEATURE_PARTIAL_READS,
44+
}) {
45+
saxParser.setFeature(feature, saxFeatures & 0x01);
46+
saxFeatures >>= 1;
47+
}
48+
49+
try {
50+
saxParser.parseString(xml);
51+
} catch (const std::exception &) {
52+
}
53+
54+
// DOM Parser
55+
56+
DOMParser domParser;
57+
std::uint8_t domFeatures = size > 0 ? data[size - 1] : 0;
58+
59+
for (const auto feature : {
60+
XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES,
61+
XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES,
62+
XMLReader::FEATURE_NAMESPACES,
63+
XMLReader::FEATURE_NAMESPACE_PREFIXES,
64+
DOMParser::FEATURE_FILTER_WHITESPACE,
65+
}) {
66+
domParser.setFeature(feature, domFeatures & 0x01);
67+
domFeatures >>= 1;
68+
}
69+
70+
try {
71+
Poco::AutoPtr<Document> doc = domParser.parseString(xml);
72+
} catch (const std::exception &) {
73+
}
74+
75+
// Stream Parser
76+
77+
std::istringstream stream(xml);
78+
79+
try {
80+
XMLStreamParser streamParser(stream, "fuzz");
81+
for (XMLStreamParser::EventType e : streamParser) {
82+
streamParser.getQName().toString();
83+
}
84+
} catch (const std::exception &) {
85+
}
86+
87+
return 0;
88+
}

0 commit comments

Comments
 (0)