Edit

kc3-lang/libxml2/fuzz/testFuzzer.c

Branch :

  • Show log

    Commit

  • Author : Nick Wellnhofer
    Date : 2023-09-21 13:05:49
    Hash : f9d717af
    Message : fuzz: Allow to fuzz without push, reader or output modules

  • fuzz/testFuzzer.c
  • /*
     * testFuzzer.c: Test program for the custom entity loader used to fuzz
     * with multiple inputs.
     *
     * See Copyright for the status of this software.
     */
    
    #include <string.h>
    #include <glob.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    #include <libxml/xmlstring.h>
    #include "fuzz.h"
    
    #ifdef HAVE_HTML_FUZZER
    int fuzzHtmlInit(int *argc, char ***argv);
    int fuzzHtml(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzHtmlInit
    #define LLVMFuzzerTestOneInput fuzzHtml
    #include "html.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    #ifdef HAVE_REGEXP_FUZZER
    int fuzzRegexpInit(int *argc, char ***argv);
    int fuzzRegexp(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzRegexpInit
    #define LLVMFuzzerTestOneInput fuzzRegexp
    #include "regexp.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    #ifdef HAVE_SCHEMA_FUZZER
    int fuzzSchemaInit(int *argc, char ***argv);
    int fuzzSchema(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzSchemaInit
    #define LLVMFuzzerTestOneInput fuzzSchema
    #include "schema.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    #ifdef HAVE_URI_FUZZER
    int fuzzUriInit(int *argc, char ***argv);
    int fuzzUri(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzUriInit
    #define LLVMFuzzerTestOneInput fuzzUri
    #include "uri.c"
    #undef LLVMFuzzerInitialize
    #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);
    #define LLVMFuzzerInitialize fuzzXIncludeInit
    #define LLVMFuzzerTestOneInput fuzzXInclude
    #include "xinclude.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    #ifdef HAVE_XML_FUZZER
    int fuzzXmlInit(int *argc, char ***argv);
    int fuzzXml(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzXmlInit
    #define LLVMFuzzerTestOneInput fuzzXml
    #include "xml.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    #ifdef HAVE_XPATH_FUZZER
    int fuzzXPathInit(int *argc, char ***argv);
    int fuzzXPath(const char *data, size_t size);
    #define LLVMFuzzerInitialize fuzzXPathInit
    #define LLVMFuzzerTestOneInput fuzzXPath
    #include "xpath.c"
    #undef LLVMFuzzerInitialize
    #undef LLVMFuzzerTestOneInput
    #endif
    
    typedef int
    (*initFunc)(int *argc, char ***argv);
    typedef int
    (*fuzzFunc)(const char *data, size_t size);
    
    int numInputs;
    
    static int
    testFuzzer(initFunc init, fuzzFunc fuzz, const char *pattern) {
        glob_t globbuf;
        int ret = -1;
        size_t i;
    
        if (glob(pattern, 0, NULL, &globbuf) != 0) {
            fprintf(stderr, "pattern %s matches no files\n", pattern);
            return(-1);
        }
    
        if (init != NULL)
            init(NULL, NULL);
    
        for (i = 0; i < globbuf.gl_pathc; i++) {
            const char *path = globbuf.gl_pathv[i];
            char *data;
            size_t size;
    
            data = xmlSlurpFile(path, &size);
            if (data == NULL) {
                fprintf(stderr, "couldn't read %s\n", path);
                goto error;
            }
            fuzz(data, size);
            xmlFree(data);
    
            numInputs++;
        }
    
        ret = 0;
    error:
        globfree(&globbuf);
        return(ret);
    }
    
    #ifdef HAVE_XML_FUZZER
    static int
    testEntityLoader(void) {
        static const char data[] =
            "doc.xml\\\n"
            "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
            "<doc>&ent;</doc>\\\n"
            "doc.dtd\\\n"
            "<!ELEMENT doc (#PCDATA)>\n"
            "<!ENTITY ent SYSTEM \"ent.txt\">\\\n"
            "ent.txt\\\n"
            "Hello, world!\\\n";
        const char *docBuffer;
        size_t docSize;
        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);
    
    #ifdef LIBXML_OUTPUT_ENABLED
        {
            static xmlChar expected[] =
                "<?xml version=\"1.0\"?>\n"
                "<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
                "<doc>Hello, world!</doc>\n";
            xmlChar *out;
    
            xmlDocDumpMemory(doc, &out, NULL);
            if (xmlStrcmp(out, expected) != 0) {
                fprintf(stderr, "Expected:\n%sGot:\n%s", expected, out);
                ret = 1;
            }
            xmlFree(out);
        }
    #endif
    
        xmlFreeDoc(doc);
        xmlFuzzDataCleanup();
    
        return(ret);
    }
    #endif
    
    int
    main(void) {
        int ret = 0;
    
    #ifdef HAVE_XML_FUZZER
        if (testEntityLoader() != 0)
            ret = 1;
    #endif
    #ifdef HAVE_HTML_FUZZER
        if (testFuzzer(fuzzHtmlInit, fuzzHtml, "seed/html/*") != 0)
            ret = 1;
    #endif
    #ifdef HAVE_REGEXP_FUZZER
        if (testFuzzer(fuzzRegexpInit, fuzzRegexp, "seed/regexp/*") != 0)
            ret = 1;
    #endif
    #ifdef HAVE_SCHEMA_FUZZER
        if (testFuzzer(fuzzSchemaInit, fuzzSchema, "seed/schema/*") != 0)
            ret = 1;
    #endif
    #ifdef HAVE_URI_FUZZER
        if (testFuzzer(fuzzUriInit, 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;
    #endif
    #ifdef HAVE_XML_FUZZER
        if (testFuzzer(fuzzXmlInit, fuzzXml, "seed/xml/*") != 0)
            ret = 1;
    #endif
    #ifdef HAVE_XPATH_FUZZER
        if (testFuzzer(fuzzXPathInit, fuzzXPath, "seed/xpath/*") != 0)
            ret = 1;
    #endif
    
        if (ret == 0)
            printf("Successfully tested %d inputs\n", numInputs);
    
        return(ret);
    }