1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 20:25:14 +03:00

fuzz: Separate fuzzer for DTD validation

This commit is contained in:
Nick Wellnhofer 2023-03-12 16:15:54 +01:00
parent a57a7549fa
commit 4eba9f9cfc
8 changed files with 154 additions and 3 deletions

1
fuzz/.gitignore vendored
View File

@ -6,6 +6,7 @@ schema
seed/
testFuzzer
uri
valid
xinclude
xml
xpath

View File

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = -Wno-syntax
EXTRA_PROGRAMS = genSeed html regexp schema uri xinclude xml xpath
EXTRA_PROGRAMS = genSeed html regexp schema uri valid 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
@ -27,7 +27,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/xinclude.stamp seed/xml.stamp seed/xpath.stamp
seed/valid.stamp seed/xinclude.stamp seed/xml.stamp seed/xpath.stamp
check-local: corpus
./testFuzzer$(EXEEXT)
@ -59,6 +59,24 @@ fuzz-xml: xml$(EXEEXT) seed/xml.stamp
-timeout=20 \
corpus/xml seed/xml
# DTD validation fuzzer
seed/valid.stamp: genSeed$(EXEEXT)
@mkdir -p seed/valid
./genSeed$(EXEEXT) valid $(XML_SEED_CORPUS_SRC)
@touch seed/valid.stamp
valid_SOURCES = valid.c fuzz.c
valid_LDFLAGS = $(AM_LDFLAGS) -fsanitize=fuzzer
fuzz-valid: valid$(EXEEXT) seed/valid.stamp
@mkdir -p corpus/valid
./valid$(EXEEXT) \
-dict=xml.dict \
-max_len=$(XML_MAX_LEN) \
-timeout=20 \
corpus/valid seed/valid
# XInclude fuzzer
seed/xinclude.stamp: genSeed$(EXEEXT)

View File

@ -27,6 +27,10 @@ extern "C" {
#if 1
#define HAVE_URI_FUZZER
#endif
#if defined(LIBXML_VALID_ENABLED) && \
defined(LIBXML_READER_ENABLED)
#define HAVE_VALID_FUZZER
#endif
#if defined(LIBXML_XINCLUDE_ENABLED) && \
defined(LIBXML_READER_ENABLED)
#define HAVE_XINCLUDE_FUZZER

View File

@ -418,6 +418,11 @@ main(int argc, const char **argv) {
#ifdef HAVE_SCHEMA_FUZZER
processArg = processPattern;
globalData.processFile = processSchema;
#endif
} else if (strcmp(fuzzer, "valid") == 0) {
#ifdef HAVE_XINCLUDE_FUZZER
processArg = processPattern;
globalData.processFile = processXml;
#endif
} else if (strcmp(fuzzer, "xinclude") == 0) {
#ifdef HAVE_XINCLUDE_FUZZER

View File

@ -52,6 +52,16 @@ int fuzzUri(const char *data, size_t size);
#undef LLVMFuzzerTestOneInput
#endif
#ifdef HAVE_VALID_FUZZER
int fuzzValidInit(int *argc, char ***argv);
int fuzzValid(const char *data, size_t size);
#define LLVMFuzzerInitialize fuzzValidInit
#define LLVMFuzzerTestOneInput fuzzValid
#include "valid.c"
#undef LLVMFuzzerInitialize
#undef LLVMFuzzerTestOneInput
#endif
#ifdef HAVE_XINCLUDE_FUZZER
int fuzzXIncludeInit(int *argc, char ***argv);
int fuzzXInclude(const char *data, size_t size);
@ -193,6 +203,10 @@ main(void) {
if (testFuzzer(NULL, fuzzUri, "seed/uri/*") != 0)
ret = 1;
#endif
#ifdef HAVE_VALID_FUZZER
if (testFuzzer(fuzzValidInit, fuzzValid, "seed/valid/*") != 0)
ret = 1;
#endif
#ifdef HAVE_XINCLUDE_FUZZER
if (testFuzzer(fuzzXIncludeInit, fuzzXInclude, "seed/xinclude/*") != 0)
ret = 1;

108
fuzz/valid.c Normal file
View File

@ -0,0 +1,108 @@
/*
* valid.c: a libFuzzer target to test DTD validation.
*
* 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/xmlreader.h>
#include "fuzz.h"
int
LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
char ***argv ATTRIBUTE_UNUSED) {
xmlFuzzMemSetup();
xmlInitParser();
#ifdef LIBXML_CATALOG_ENABLED
xmlInitializeCatalog();
#endif
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;
xmlValidCtxtPtr vctxt;
xmlTextReaderPtr reader;
const char *docBuffer, *docUrl;
size_t maxAlloc, docSize, consumed, chunkSize;
int opts;
xmlFuzzDataInit(data, size);
opts = (int) xmlFuzzReadInt(4);
opts &= ~XML_PARSE_XINCLUDE;
opts |= XML_PARSE_DTDVALID;
maxAlloc = xmlFuzzReadInt(4) % (size + 1);
xmlFuzzReadEntities();
docBuffer = xmlFuzzMainEntity(&docSize);
docUrl = xmlFuzzMainUrl();
if (docBuffer == NULL)
goto exit;
/* Pull parser */
xmlFuzzMemSetLimit(maxAlloc);
doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts);
xmlFreeDoc(doc);
/* Post validation */
xmlFuzzMemSetLimit(maxAlloc);
doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL, opts & ~XML_PARSE_DTDVALID);
vctxt = xmlNewValidCtxt();
xmlValidateDocument(vctxt, doc);
xmlFreeValidCtxt(vctxt);
xmlFreeDoc(doc);
/* Push parser */
xmlFuzzMemSetLimit(maxAlloc);
ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
if (ctxt == NULL)
goto exit;
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 */
xmlFuzzMemSetLimit(maxAlloc);
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:
xmlFuzzMemSetLimit(0);
xmlFuzzDataCleanup();
xmlResetLastError();
return(0);
}

View File

@ -36,6 +36,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlFuzzDataInit(data, size);
opts = (int) xmlFuzzReadInt(4);
opts &= ~XML_PARSE_DTDVALID;
opts |= XML_PARSE_XINCLUDE;
maxAlloc = xmlFuzzReadInt(4) % (size + 1);

View File

@ -38,7 +38,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
xmlFuzzDataInit(data, size);
opts = (int) xmlFuzzReadInt(4);
opts &= ~XML_PARSE_XINCLUDE;
opts &= ~XML_PARSE_XINCLUDE & ~XML_PARSE_DTDVALID;
maxAlloc = xmlFuzzReadInt(4) % (size + 1);
xmlFuzzReadEntities();