Edit

kc3-lang/libxml2/fuzz/xml.c

Branch :

  • Show log

    Commit

  • Author : Nick Wellnhofer
    Date : 2021-02-22 21:28:21
    Hash : 85c817a2
    Message : Improve fuzzer stability - Add more calls to xmlInitializeCatalog. - Call xmlResetLastError after fuzzing each input.

  • fuzz/xml.c
  • /*
     * xml.c: a libFuzzer target to test several XML parser interfaces.
     *
     * 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/xinclude.h>
    #include <libxml/xmlreader.h>
    #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<n; i++) {
                    xmlTextReaderMoveToAttributeNo(reader, i);
                    while (xmlTextReaderReadAttributeValue(reader) == 1);
                }
            }
        }
        xmlFreeTextReader(reader);
    
    exit:
        xmlFuzzDataCleanup();
        xmlResetLastError();
        return(0);
    }