/* * xml.c: a libFuzzer target to test several XML parser interfaces. * * See Copyright for the status of this software. */ #include #include #include #include #include #include #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) { static const size_t maxChunkSize = 128; xmlDocPtr doc; xmlParserCtxtPtr ctxt; xmlTextReaderPtr reader; xmlChar *out; const char *docBuffer, *docUrl; size_t maxSize, docSize, consumed, chunkSize; int opts, outSize; xmlFuzzDataInit(data, size); opts = xmlFuzzReadInt(); /* Lower maximum size when processing entities for now. */ maxSize = opts & XML_PARSE_NOENT ? 50000 : 500000; if (size > maxSize) goto exit; xmlFuzzReadEntities(); docBuffer = xmlFuzzMainEntity(&docSize); docUrl = xmlFuzzMainUrl(); if (docBuffer == NULL) goto exit; /* 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); xmlFreeDoc(doc); /* Push parser */ 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); if (opts & XML_PARSE_XINCLUDE) xmlXIncludeProcessFlags(ctxt->myDoc, opts); xmlFreeDoc(ctxt->myDoc); xmlFreeParserCtxt(ctxt); /* 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