mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-12-23 17:33:50 +03:00
fuzz: Add separate XInclude fuzzer
XIncludes involve XPath processing which can still lead to timeouts when fuzzing. This will probably take a while to fix. The rest of the XML parsing code should hopefully run without timeouts now. OSS-Fuzz only shows a single timeout test case, so separate the XInclude from the core XML fuzzer.
This commit is contained in:
parent
66e9fd66e8
commit
09dac45ab9
@ -1,5 +1,5 @@
|
||||
AUTOMAKE_OPTIONS = -Wno-syntax
|
||||
EXTRA_PROGRAMS = genSeed html regexp schema uri xml xpath
|
||||
EXTRA_PROGRAMS = genSeed html regexp schema uri xinclude xml xpath
|
||||
check_PROGRAMS = testFuzzer
|
||||
EXTRA_DIST = html.dict regexp.dict schema.dict xml.dict xpath.dict \
|
||||
static_seed/uri static_seed/regexp fuzz.h
|
||||
@ -19,8 +19,6 @@ XML_SEED_CORPUS_SRC = \
|
||||
'$(top_srcdir)/test/valid/*.xml' \
|
||||
'$(top_srcdir)/test/VC/*' \
|
||||
'$(top_srcdir)/test/VCM/*' \
|
||||
'$(top_srcdir)/test/XInclude/docs/*' \
|
||||
'$(top_srcdir)/test/XInclude/without-reader/*' \
|
||||
'$(top_srcdir)/test/xmlid/*'
|
||||
|
||||
testFuzzer_SOURCES = testFuzzer.c fuzz.c
|
||||
@ -28,7 +26,7 @@ testFuzzer_SOURCES = testFuzzer.c fuzz.c
|
||||
.PHONY: corpus clean-corpus
|
||||
|
||||
corpus: seed/html.stamp seed/regexp.stamp seed/schema.stamp seed/uri.stamp \
|
||||
seed/xml.stamp seed/xpath.stamp
|
||||
seed/xinclude.stamp seed/xml.stamp seed/xpath.stamp
|
||||
|
||||
check-local: corpus
|
||||
./testFuzzer$(EXEEXT)
|
||||
@ -60,6 +58,26 @@ fuzz-xml: xml$(EXEEXT) seed/xml.stamp
|
||||
-timeout=20 \
|
||||
corpus/xml seed/xml
|
||||
|
||||
# XInclude fuzzer
|
||||
|
||||
seed/xinclude.stamp: genSeed$(EXEEXT)
|
||||
@mkdir -p seed/xinclude
|
||||
./genSeed$(EXEEXT) xinclude \
|
||||
'$(top_srcdir)/test/XInclude/docs/*' \
|
||||
'$(top_srcdir)/test/XInclude/without-reader/*'
|
||||
@touch seed/xinclude.stamp
|
||||
|
||||
xinclude_SOURCES = xinclude.c fuzz.c
|
||||
xinclude_LDFLAGS = $(AM_LDFLAGS) -fsanitize=fuzzer
|
||||
|
||||
fuzz-xinclude: xinclude$(EXEEXT) seed/xinclude.stamp
|
||||
@mkdir -p corpus/xinclude
|
||||
./xinclude$(EXEEXT) \
|
||||
-dict=xml.dict \
|
||||
-max_len=$(XML_MAX_LEN) \
|
||||
-timeout=20 \
|
||||
corpus/xinclude seed/xinclude
|
||||
|
||||
# HTML fuzzer
|
||||
|
||||
seed/html.stamp: genSeed$(EXEEXT)
|
||||
|
@ -27,9 +27,12 @@ extern "C" {
|
||||
#if 1
|
||||
#define HAVE_URI_FUZZER
|
||||
#endif
|
||||
#if defined(LIBXML_XINCLUDE_ENABLED) && \
|
||||
defined(LIBXML_READER_ENABLED)
|
||||
#define HAVE_XINCLUDE_FUZZER
|
||||
#endif
|
||||
#if defined(LIBXML_OUTPUT_ENABLED) && \
|
||||
defined(LIBXML_READER_ENABLED) && \
|
||||
defined(LIBXML_XINCLUDE_ENABLED)
|
||||
defined(LIBXML_READER_ENABLED)
|
||||
#define HAVE_XML_FUZZER
|
||||
#endif
|
||||
#if defined(LIBXML_XPATH_ENABLED)
|
||||
|
@ -406,6 +406,11 @@ main(int argc, const char **argv) {
|
||||
#ifdef HAVE_SCHEMA_FUZZER
|
||||
processArg = processPattern;
|
||||
globalData.processFile = processSchema;
|
||||
#endif
|
||||
} else if (strcmp(fuzzer, "xinclude") == 0) {
|
||||
#ifdef HAVE_XINCLUDE_FUZZER
|
||||
processArg = processPattern;
|
||||
globalData.processFile = processXml;
|
||||
#endif
|
||||
} else if (strcmp(fuzzer, "xml") == 0) {
|
||||
#ifdef HAVE_XML_FUZZER
|
||||
|
@ -52,6 +52,16 @@ int fuzzUri(const char *data, size_t size);
|
||||
#undef LLVMFuzzerTestOneInput
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XINCLUDE_FUZZER
|
||||
int fuzzXIncludeInit(int *argc, char ***argv);
|
||||
int fuzzXInclude(const char *data, size_t size);
|
||||
#define LLVMFuzzerInitialize fuzzXIncludeInit
|
||||
#define LLVMFuzzerTestOneInput fuzzXInclude
|
||||
#include "xinclude.c"
|
||||
#undef LLVMFuzzerInitialize
|
||||
#undef LLVMFuzzerTestOneInput
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XML_FUZZER
|
||||
int fuzzXmlInit(int *argc, char ***argv);
|
||||
int fuzzXml(const char *data, size_t size);
|
||||
@ -183,6 +193,10 @@ main(void) {
|
||||
if (testFuzzer(NULL, fuzzUri, "seed/uri/*") != 0)
|
||||
ret = 1;
|
||||
#endif
|
||||
#ifdef HAVE_XINCLUDE_FUZZER
|
||||
if (testFuzzer(fuzzXIncludeInit, fuzzXInclude, "seed/xinclude/*") != 0)
|
||||
ret = 1;
|
||||
#endif
|
||||
#ifdef HAVE_XML_FUZZER
|
||||
if (testFuzzer(fuzzXmlInit, fuzzXml, "seed/xml/*") != 0)
|
||||
ret = 1;
|
||||
|
73
fuzz/xinclude.c
Normal file
73
fuzz/xinclude.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* xinclude.c: a libFuzzer target to test the XInclude engine.
|
||||
*
|
||||
* See Copyright for the status of this software.
|
||||
*/
|
||||
|
||||
#include <libxml/catalog.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/xmlerror.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include "fuzz.h"
|
||||
|
||||
int
|
||||
LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
char ***argv ATTRIBUTE_UNUSED) {
|
||||
xmlInitParser();
|
||||
#ifdef LIBXML_CATALOG_ENABLED
|
||||
xmlInitializeCatalog();
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlDocPtr doc;
|
||||
xmlTextReaderPtr reader;
|
||||
const char *docBuffer, *docUrl;
|
||||
size_t docSize;
|
||||
int opts;
|
||||
|
||||
xmlFuzzDataInit(data, size);
|
||||
opts = xmlFuzzReadInt();
|
||||
opts |= XML_PARSE_XINCLUDE;
|
||||
|
||||
xmlFuzzReadEntities();
|
||||
docBuffer = xmlFuzzMainEntity(&docSize);
|
||||
docUrl = xmlFuzzMainUrl();
|
||||
if (docBuffer == NULL)
|
||||
goto exit;
|
||||
|
||||
/* Pull parser */
|
||||
|
||||
doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
|
||||
xmlXIncludeProcessFlags(doc, opts);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
/* Reader */
|
||||
|
||||
reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
|
||||
if (reader == NULL)
|
||||
goto exit;
|
||||
while (xmlTextReaderRead(reader) == 1) {
|
||||
if (xmlTextReaderNodeType(reader) == XML_ELEMENT_NODE) {
|
||||
int i, n = xmlTextReaderAttributeCount(reader);
|
||||
for (i=0; i<n; i++) {
|
||||
xmlTextReaderMoveToAttributeNo(reader, i);
|
||||
while (xmlTextReaderReadAttributeValue(reader) == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFreeTextReader(reader);
|
||||
|
||||
exit:
|
||||
xmlFuzzDataCleanup();
|
||||
xmlResetLastError();
|
||||
return(0);
|
||||
}
|
||||
|
3
fuzz/xinclude.options
Normal file
3
fuzz/xinclude.options
Normal file
@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
dict = xml.dict
|
||||
timeout = 20
|
@ -8,7 +8,6 @@
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/xmlerror.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include "fuzz.h"
|
||||
|
||||
@ -49,8 +48,6 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
/* Pull parser */
|
||||
|
||||
doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
|
||||
if (opts & XML_PARSE_XINCLUDE)
|
||||
xmlXIncludeProcessFlags(doc, opts);
|
||||
/* Also test the serializer. */
|
||||
xmlDocDumpMemory(doc, &out, &outSize);
|
||||
xmlFree(out);
|
||||
@ -71,8 +68,6 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
}
|
||||
|
||||
xmlParseChunk(ctxt, NULL, 0, 1);
|
||||
if (opts & XML_PARSE_XINCLUDE)
|
||||
xmlXIncludeProcessFlags(ctxt->myDoc, opts);
|
||||
xmlFreeDoc(ctxt->myDoc);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user