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:
parent
a57a7549fa
commit
4eba9f9cfc
1
fuzz/.gitignore
vendored
1
fuzz/.gitignore
vendored
@ -6,6 +6,7 @@ schema
|
||||
seed/
|
||||
testFuzzer
|
||||
uri
|
||||
valid
|
||||
xinclude
|
||||
xml
|
||||
xpath
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
108
fuzz/valid.c
Normal 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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user