libxml2_xml_saxparser_fuzzer.cc [plain text]
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
#include <string>
#include "libxml/parser.h"
#include "libxml/parserInternals.h"
#include "libxml/xmlsave.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
static void errorCallback(void* ctx, const char* msg, ...) {
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)ctx;
xmlErrorPtr error = xmlCtxtGetLastError(ctxt);
if (error != NULL && error->level == XML_ERR_FATAL)
xmlStopParser(ctxt);
}
static xmlSAXHandler xmlSAXHandlerStruct = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
errorCallback,
NULL,
NULL,
NULL,
NULL,
XML_SAX2_MAGIC,
NULL,
NULL,
NULL,
NULL
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::string data_string(reinterpret_cast<const char*>(data), size);
const std::size_t data_hash = std::hash<std::string>()(data_string);
const int max_option_value = std::numeric_limits<int>::max();
const int random_option_value = data_hash % max_option_value;
const int options[] = {0, random_option_value};
for (const auto option_value : options) {
if (xmlParserInputBufferPtr inputBuffer = xmlParserInputBufferCreateMem((const char*)data, (int)size, XML_CHAR_ENCODING_NONE)) {
if (xmlParserCtxtPtr ctxt = xmlNewParserCtxt()) {
xmlCtxtUseOptions(ctxt, option_value | XML_PARSE_NOENT | XML_PARSE_NONET);
xmlSAXHandlerPtr handler = &xmlSAXHandlerStruct;
xmlSAXHandlerPtr old_sax = ctxt->sax;
ctxt->sax = handler;
ctxt->userData = ctxt;
if (xmlParserInputPtr inputStream = xmlNewIOInputStream(ctxt, inputBuffer, XML_CHAR_ENCODING_NONE)) {
inputPush(ctxt, inputStream);
xmlParseDocument(ctxt);
if (xmlDocPtr doc = ctxt->myDoc) {
ctxt->myDoc = nullptr;
auto buf = xmlBufferCreate();
assert(buf);
auto ctxtSave = xmlSaveToBuffer(buf, NULL, 0);
xmlSaveDoc(ctxtSave, doc);
xmlSaveClose(ctxtSave);
xmlFreeDoc(doc);
}
}
ctxt->sax = old_sax;
xmlFreeParserCtxt(ctxt);
}
}
}
return 0;
}