mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2024-12-24 21:33:51 +03:00
fuzz: Move to per-context resource loader
This commit is contained in:
parent
89fcae4dfd
commit
116d8c0166
@ -964,7 +964,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
27
fuzz/fuzz.c
27
fuzz/fuzz.c
@ -386,6 +386,33 @@ xmlFuzzMainEntity(size_t *size) {
|
||||
return(fuzzData.mainEntity->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFuzzResourceLoader:
|
||||
*
|
||||
* The resource loader for fuzz data.
|
||||
*/
|
||||
int
|
||||
xmlFuzzResourceLoader(void *data ATTRIBUTE_UNUSED, const char *URL,
|
||||
const char *ID ATTRIBUTE_UNUSED,
|
||||
int type ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
|
||||
xmlParserInputPtr *out) {
|
||||
xmlParserInputPtr input;
|
||||
xmlFuzzEntityInfo *entity;
|
||||
|
||||
entity = xmlHashLookup(fuzzData.entities, (xmlChar *) URL);
|
||||
if (entity == NULL)
|
||||
return(XML_IO_ENOENT);
|
||||
|
||||
input = xmlInputCreateMemory(URL, entity->data, entity->size,
|
||||
XML_INPUT_BUF_STATIC |
|
||||
XML_INPUT_BUF_ZERO_TERMINATED);
|
||||
if (input == NULL)
|
||||
return(XML_ERR_NO_MEMORY);
|
||||
|
||||
*out = input;
|
||||
return(XML_ERR_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFuzzEntityLoader:
|
||||
*
|
||||
|
@ -104,6 +104,10 @@ xmlFuzzMainUrl(void);
|
||||
const char *
|
||||
xmlFuzzMainEntity(size_t *size);
|
||||
|
||||
int
|
||||
xmlFuzzResourceLoader(void *data, const char *URL, const char *ID,
|
||||
int type, int flags, xmlParserInputPtr *out);
|
||||
|
||||
xmlParserInputPtr
|
||||
xmlFuzzEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt);
|
||||
|
||||
|
@ -50,25 +50,30 @@ static struct {
|
||||
#if defined(HAVE_SCHEMA_FUZZER) || \
|
||||
defined(HAVE_XML_FUZZER)
|
||||
/*
|
||||
* A custom entity loader that writes all external DTDs or entities to a
|
||||
* single file in the format expected by xmlFuzzEntityLoader.
|
||||
* A custom resource loader that writes all external DTDs or entities to a
|
||||
* single file in the format expected by xmlFuzzResourceLoader.
|
||||
*/
|
||||
static xmlParserInputPtr
|
||||
fuzzEntityRecorder(const char *URL, const char *ID,
|
||||
xmlParserCtxtPtr ctxt) {
|
||||
static int
|
||||
fuzzResourceRecorder(void *data ATTRIBUTE_UNUSED, const char *URL,
|
||||
const char *ID ATTRIBUTE_UNUSED,
|
||||
int type ATTRIBUTE_UNUSED, int flags,
|
||||
xmlParserInputPtr *out) {
|
||||
xmlParserInputPtr in;
|
||||
static const int chunkSize = 16384;
|
||||
int len;
|
||||
int code, len;
|
||||
|
||||
in = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
|
||||
if (in == NULL)
|
||||
return(NULL);
|
||||
*out = NULL;
|
||||
|
||||
code = xmlInputCreateUrl(URL, flags, &in);
|
||||
if (code != XML_ERR_OK)
|
||||
return(code);
|
||||
|
||||
if (globalData.entities == NULL) {
|
||||
globalData.entities = xmlHashCreate(4);
|
||||
} else if (xmlHashLookup(globalData.entities,
|
||||
(const xmlChar *) URL) != NULL) {
|
||||
return(in);
|
||||
*out = in;
|
||||
return(XML_ERR_OK);
|
||||
}
|
||||
|
||||
do {
|
||||
@ -76,7 +81,7 @@ fuzzEntityRecorder(const char *URL, const char *ID,
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "Error reading %s\n", URL);
|
||||
xmlFreeInputStream(in);
|
||||
return(NULL);
|
||||
return(in->buf->error);
|
||||
}
|
||||
} while (len > 0);
|
||||
|
||||
@ -89,7 +94,7 @@ fuzzEntityRecorder(const char *URL, const char *ID,
|
||||
xmlHashAddEntry(globalData.entities, (const xmlChar *) URL,
|
||||
globalData.entities);
|
||||
|
||||
return(xmlNoNetExternalEntityLoader(URL, ID, ctxt));
|
||||
return(xmlInputCreateUrl(URL, flags, out));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -97,12 +102,10 @@ fuzzRecorderInit(FILE *out) {
|
||||
globalData.out = out;
|
||||
globalData.entities = xmlHashCreate(8);
|
||||
globalData.oldLoader = xmlGetExternalEntityLoader();
|
||||
xmlSetExternalEntityLoader(fuzzEntityRecorder);
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzRecorderCleanup(void) {
|
||||
xmlSetExternalEntityLoader(globalData.oldLoader);
|
||||
xmlHashFree(globalData.entities, NULL);
|
||||
globalData.out = NULL;
|
||||
globalData.entities = NULL;
|
||||
@ -114,6 +117,7 @@ fuzzRecorderCleanup(void) {
|
||||
static int
|
||||
processXml(const char *docFile, FILE *out) {
|
||||
int opts = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
|
||||
xmlParserCtxtPtr ctxt;
|
||||
xmlDocPtr doc;
|
||||
|
||||
if (globalData.flags & FLAG_LINT) {
|
||||
@ -146,11 +150,21 @@ processXml(const char *docFile, FILE *out) {
|
||||
|
||||
fuzzRecorderInit(out);
|
||||
|
||||
doc = xmlReadFile(docFile, NULL, opts);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
xmlCtxtSetResourceLoader(ctxt, fuzzResourceRecorder, NULL);
|
||||
doc = xmlCtxtReadFile(ctxt, docFile, NULL, opts);
|
||||
#ifdef LIBXML_XINCLUDE_ENABLED
|
||||
xmlXIncludeProcessFlags(doc, opts);
|
||||
{
|
||||
xmlXIncludeCtxtPtr xinc = xmlXIncludeNewContext(doc);
|
||||
|
||||
xmlXIncludeSetResourceLoader(xinc, fuzzResourceRecorder, NULL);
|
||||
xmlXIncludeSetFlags(xinc, opts);
|
||||
xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc);
|
||||
xmlXIncludeFreeContext(xinc);
|
||||
}
|
||||
#endif
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
fuzzRecorderCleanup();
|
||||
|
||||
@ -200,6 +214,7 @@ processSchema(const char *docFile, FILE *out) {
|
||||
|
||||
pctxt = xmlSchemaNewParserCtxt(docFile);
|
||||
xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
|
||||
xmlSchemaSetResourceLoader(pctxt, fuzzResourceRecorder, NULL);
|
||||
schema = xmlSchemaParse(pctxt);
|
||||
xmlSchemaFreeParserCtxt(pctxt);
|
||||
xmlSchemaFree(schema);
|
||||
|
@ -102,7 +102,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -137,6 +136,8 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
if (reader == NULL)
|
||||
goto exit;
|
||||
|
||||
xmlTextReaderSetResourceLoader(reader, xmlFuzzResourceLoader, NULL);
|
||||
|
||||
i = 0;
|
||||
while (i < programSize) {
|
||||
int op = program[i++];
|
||||
|
@ -18,7 +18,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -39,6 +38,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
pctxt = xmlSchemaNewParserCtxt(xmlFuzzMainUrl());
|
||||
xmlSchemaSetParserErrors(pctxt, xmlFuzzErrorFunc, xmlFuzzErrorFunc, NULL);
|
||||
xmlSchemaSetResourceLoader(pctxt, xmlFuzzResourceLoader, NULL);
|
||||
xmlSchemaFree(xmlSchemaParse(pctxt));
|
||||
xmlSchemaFreeParserCtxt(pctxt);
|
||||
|
||||
|
@ -148,6 +148,7 @@ error:
|
||||
#ifdef HAVE_XML_FUZZER
|
||||
static int
|
||||
testEntityLoader(void) {
|
||||
xmlParserCtxtPtr ctxt;
|
||||
static const char data[] =
|
||||
"doc.xml\\\n"
|
||||
"<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
|
||||
@ -162,13 +163,14 @@ testEntityLoader(void) {
|
||||
xmlDocPtr doc;
|
||||
int ret = 0;
|
||||
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
xmlFuzzDataInit(data, sizeof(data) - 1);
|
||||
xmlFuzzReadEntities();
|
||||
docBuffer = xmlFuzzMainEntity(&docSize);
|
||||
doc = xmlReadMemory(docBuffer, docSize, NULL, NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, NULL, NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
{
|
||||
|
24
fuzz/valid.c
24
fuzz/valid.c
@ -20,7 +20,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -51,6 +50,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
if (ctxt != NULL) {
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
|
||||
xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
|
||||
ctxt->errNo == XML_ERR_NO_MEMORY);
|
||||
@ -61,12 +61,21 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
/* Post validation */
|
||||
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
doc = xmlReadMemory(docBuffer, docSize, docUrl, NULL,
|
||||
opts & ~XML_PARSE_DTDVALID);
|
||||
vctxt = xmlNewValidCtxt();
|
||||
xmlValidateDocument(vctxt, doc);
|
||||
xmlFreeValidCtxt(vctxt);
|
||||
xmlFreeDoc(doc);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
if (ctxt != NULL) {
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL,
|
||||
opts & ~XML_PARSE_DTDVALID);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
/* Post validation requires global callbacks */
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
vctxt = xmlNewValidCtxt();
|
||||
xmlValidateDocument(vctxt, doc);
|
||||
xmlFreeValidCtxt(vctxt);
|
||||
xmlFreeDoc(doc);
|
||||
xmlSetExternalEntityLoader(NULL);
|
||||
}
|
||||
|
||||
/* Push parser */
|
||||
|
||||
@ -78,6 +87,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
|
||||
if (ctxt != NULL) {
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
xmlCtxtUseOptions(ctxt, opts);
|
||||
|
||||
for (consumed = 0; consumed < docSize; consumed += chunkSize) {
|
||||
|
@ -21,7 +21,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -53,11 +52,14 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlXIncludeCtxtPtr xinc;
|
||||
xmlDocPtr copy;
|
||||
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
|
||||
doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
|
||||
xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
|
||||
ctxt->errNo == XML_ERR_NO_MEMORY);
|
||||
|
||||
xinc = xmlXIncludeNewContext(doc);
|
||||
xmlXIncludeSetResourceLoader(xinc, xmlFuzzResourceLoader, NULL);
|
||||
xmlXIncludeSetFlags(xinc, opts);
|
||||
xmlXIncludeProcessNode(xinc, (xmlNodePtr) doc);
|
||||
if (doc != NULL) {
|
||||
|
@ -21,7 +21,6 @@ LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
|
||||
xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
|
||||
#endif
|
||||
xmlSetGenericErrorFunc(NULL, xmlFuzzErrorFunc);
|
||||
xmlSetExternalEntityLoader(xmlFuzzEntityLoader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -55,6 +54,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
if (ctxt != NULL) {
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
doc = xmlCtxtReadMemory(ctxt, docBuffer, docSize, docUrl, NULL, opts);
|
||||
xmlFuzzCheckMallocFailure("xmlCtxtReadMemory",
|
||||
doc == NULL &&
|
||||
@ -94,6 +94,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
xmlFuzzMemSetLimit(maxAlloc);
|
||||
ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, docUrl);
|
||||
if (ctxt != NULL) {
|
||||
xmlCtxtSetResourceLoader(ctxt, xmlFuzzResourceLoader, NULL);
|
||||
xmlCtxtUseOptions(ctxt, opts);
|
||||
|
||||
for (consumed = 0; consumed < docSize; consumed += chunkSize) {
|
||||
|
Loading…
Reference in New Issue
Block a user