Edit

kc3-lang/libxml2/fuzz/reader.c

Branch :

  • Show log

    Commit

  • Author : Nick Wellnhofer
    Date : 2024-07-10 22:11:08
    Hash : ae6e2ee7
    Message : fuzz: Adjust reader fuzzer

  • fuzz/reader.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/xmlreader.h>
    #include <libxml/xmlsave.h>
    #include "fuzz.h"
    
    #include <string.h>
    
    #if 0
      #define DEBUG
    #endif
    
    typedef enum {
        OP_READ = 1,
        OP_READ_INNER_XML,
        OP_READ_OUTER_XML,
        OP_READ_STRING,
        OP_READ_ATTRIBUTE_VALUE,
        OP_ATTRIBUTE_COUNT,
        OP_DEPTH,
        OP_HAS_ATTRIBUTES,
        OP_HAS_VALUE,
        OP_IS_DEFAULT,
        OP_IS_EMPTY_ELEMENT,
        OP_NODE_TYPE,
        OP_QUOTE_CHAR,
        OP_READ_STATE,
        OP_IS_NAMESPACE_DECL,
        OP_CONST_BASE_URI,
        OP_CONST_LOCAL_NAME,
        OP_CONST_NAME,
        OP_CONST_NAMESPACE_URI,
        OP_CONST_PREFIX,
        OP_CONST_XML_LANG,
        OP_CONST_VALUE,
        OP_BASE_URI,
        OP_LOCAL_NAME,
        OP_NAME,
        OP_NAMESPACE_URI,
        OP_PREFIX,
        OP_XML_LANG,
        OP_VALUE,
        OP_CLOSE,
        OP_GET_ATTRIBUTE_NO,
        OP_GET_ATTRIBUTE,
        OP_GET_ATTRIBUTE_NS,
        OP_GET_REMAINDER,
        OP_LOOKUP_NAMESPACE,
        OP_MOVE_TO_ATTRIBUTE_NO,
        OP_MOVE_TO_ATTRIBUTE,
        OP_MOVE_TO_ATTRIBUTE_NS,
        OP_MOVE_TO_FIRST_ATTRIBUTE,
        OP_MOVE_TO_NEXT_ATTRIBUTE,
        OP_MOVE_TO_ELEMENT,
        OP_NORMALIZATION,
        OP_CONST_ENCODING,
        OP_GET_PARSER_PROP,
        OP_CURRENT_NODE,
        OP_GET_PARSER_LINE_NUMBER,
        OP_GET_PARSER_COLUMN_NUMBER,
        OP_PRESERVE,
        OP_CURRENT_DOC,
        OP_EXPAND,
        OP_NEXT,
        OP_NEXT_SIBLING,
        OP_IS_VALID,
        OP_CONST_XML_VERSION,
        OP_STANDALONE,
        OP_BYTE_CONSUMED,
    
        OP_MAX
    } opType;
    
    static void
    startOp(const char *name) {
        (void) name;
    #ifdef DEBUG
        fprintf(stderr, "%s\n", name);
    #endif
    }
    
    int
    LLVMFuzzerInitialize(int *argc ATTRIBUTE_UNUSED,
                         char ***argv ATTRIBUTE_UNUSED) {
        xmlFuzzMemSetup();
        xmlInitParser();
    #ifdef LIBXML_CATALOG_ENABLED
        xmlInitializeCatalog();
        xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
    #endif
    
        return 0;
    }
    
    int
    LLVMFuzzerTestOneInput(const char *data, size_t size) {
        xmlTextReaderPtr reader;
        xmlDocPtr doc = NULL;
        const xmlError *error;
        const char *docBuffer;
        const unsigned char *program;
        size_t maxAlloc, docSize, programSize, i;
        size_t totalStringSize = 0;
        int opts;
        int oomReport = 0;
    
        xmlFuzzDataInit(data, size);
        opts = (int) xmlFuzzReadInt(4);
        maxAlloc = xmlFuzzReadInt(4) % (size + 100);
    
        program = (const unsigned char *) xmlFuzzReadString(&programSize);
        if (programSize > 1000)
            programSize = 1000;
    
        xmlFuzzReadEntities();
        docBuffer = xmlFuzzMainEntity(&docSize);
        if (docBuffer == NULL)
            goto exit;
    
    #ifdef DEBUG
        fprintf(stderr, "Input document (%d bytes):\n", (int) docSize);
        for (i = 0; (size_t) i < docSize; i++) {
            int c = (unsigned char) docBuffer[i];
    
            if ((c == '\n' || (c >= 0x20 && c <= 0x7E)))
                putc(c, stderr);
            else
                fprintf(stderr, "\\x%02X", c);
        }
        fprintf(stderr, "\nEOF\n");
    #endif
    
        xmlFuzzMemSetLimit(maxAlloc);
        reader = xmlReaderForMemory(docBuffer, docSize, NULL, NULL, opts);
        if (reader == NULL)
            goto exit;
    
        xmlTextReaderSetStructuredErrorHandler(reader, xmlFuzzSErrorFunc, NULL);
        xmlTextReaderSetResourceLoader(reader, xmlFuzzResourceLoader, NULL);
    
        i = 0;
        while (i < programSize) {
            int op = program[i++];
    
    #define READ_BYTE() (i < programSize ? program[i++] : 0)
    #define FREE_STRING(str) \
        do { \
            if (str != NULL) { \
                totalStringSize += strlen((char *) str); \
                xmlFree(str); \
            } \
        } while (0)
    
            switch (op & 0x3F) {
                case OP_READ:
                default:
                    startOp("Read");
                    xmlTextReaderRead(reader);
                    break;
    
                case OP_READ_INNER_XML: {
                    xmlChar *result;
    
                    startOp("ReadInnerXml");
                    result = xmlTextReaderReadInnerXml(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_READ_OUTER_XML: {
                    xmlChar *result;
    
                    startOp("ReadOuterXml");
                    result = xmlTextReaderReadOuterXml(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_READ_STRING: {
                    xmlChar *result;
    
                    startOp("ReadString");
                    result = xmlTextReaderReadString(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_READ_ATTRIBUTE_VALUE:
                    startOp("ReadAttributeValue");
                    xmlTextReaderReadAttributeValue(reader);
                    break;
    
                case OP_ATTRIBUTE_COUNT:
                    startOp("AttributeCount");
                    xmlTextReaderAttributeCount(reader);
                    break;
    
                case OP_DEPTH:
                    startOp("Depth");
                    xmlTextReaderDepth(reader);
                    break;
    
                case OP_HAS_ATTRIBUTES:
                    startOp("HasAttributes");
                    xmlTextReaderHasAttributes(reader);
                    break;
    
                case OP_HAS_VALUE:
                    startOp("HasValue");
                    xmlTextReaderHasValue(reader);
                    break;
    
                case OP_IS_DEFAULT:
                    startOp("IsDefault");
                    xmlTextReaderIsDefault(reader);
                    break;
    
                case OP_IS_EMPTY_ELEMENT:
                    startOp("IsEmptyElement");
                    xmlTextReaderIsEmptyElement(reader);
                    break;
    
                case OP_NODE_TYPE:
                    startOp("NodeType");
                    xmlTextReaderNodeType(reader);
                    break;
    
                case OP_QUOTE_CHAR:
                    startOp("QuoteChar");
                    xmlTextReaderQuoteChar(reader);
                    break;
    
                case OP_READ_STATE:
                    startOp("ReadState");
                    xmlTextReaderReadState(reader);
                    break;
    
                case OP_IS_NAMESPACE_DECL:
                    startOp("IsNamespaceDecl");
                    xmlTextReaderIsNamespaceDecl(reader);
                    break;
    
                case OP_CONST_BASE_URI:
                    startOp("ConstBaseUri");
                    xmlTextReaderConstBaseUri(reader);
                    break;
    
                case OP_CONST_LOCAL_NAME:
                    startOp("ConstLocalName");
                    xmlTextReaderConstLocalName(reader);
                    break;
    
                case OP_CONST_NAME:
                    startOp("ConstName");
                    xmlTextReaderConstName(reader);
                    break;
    
                case OP_CONST_NAMESPACE_URI:
                    startOp("ConstNamespaceUri");
                    xmlTextReaderConstNamespaceUri(reader);
                    break;
    
                case OP_CONST_PREFIX:
                    startOp("ConstPrefix");
                    xmlTextReaderConstPrefix(reader);
                    break;
    
                case OP_CONST_XML_LANG:
                    startOp("ConstXmlLang");
                    xmlTextReaderConstXmlLang(reader);
                    oomReport = -1;
                    break;
    
                case OP_CONST_VALUE:
                    startOp("ConstValue");
                    xmlTextReaderConstValue(reader);
                    break;
    
                case OP_BASE_URI: {
                    xmlChar *result;
    
                    startOp("BaseUri");
                    result = xmlTextReaderBaseUri(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_LOCAL_NAME: {
                    xmlChar *result;
    
                    startOp("LocalName");
                    result = xmlTextReaderLocalName(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_NAME: {
                    xmlChar *result;
    
                    startOp("Name");
                    result = xmlTextReaderName(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_NAMESPACE_URI: {
                    xmlChar *result;
    
                    startOp("NamespaceUri");
                    result = xmlTextReaderNamespaceUri(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_PREFIX: {
                    xmlChar *result;
    
                    startOp("Prefix");
                    result = xmlTextReaderPrefix(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_XML_LANG: {
                    xmlChar *result;
    
                    startOp("XmlLang");
                    result = xmlTextReaderXmlLang(reader);
                    oomReport = -1;
                    FREE_STRING(result);
                    break;
                }
    
                case OP_VALUE: {
                    xmlChar *result;
    
                    startOp("Value");
                    result = xmlTextReaderValue(reader);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_CLOSE:
                    startOp("Close");
                    if (doc == NULL)
                        doc = xmlTextReaderCurrentDoc(reader);
                    xmlTextReaderClose(reader);
                    break;
    
                case OP_GET_ATTRIBUTE_NO: {
                    xmlChar *result;
                    int no = READ_BYTE();
    
                    startOp("GetAttributeNo");
                    result = xmlTextReaderGetAttributeNo(reader, no);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_GET_ATTRIBUTE: {
                    const xmlChar *name = xmlTextReaderConstName(reader);
                    xmlChar *result;
    
                    startOp("GetAttribute");
                    result = xmlTextReaderGetAttribute(reader, name);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_GET_ATTRIBUTE_NS: {
                    const xmlChar *localName, *namespaceUri;
                    xmlChar *result;
    
                    startOp("GetAttributeNs");
                    localName = xmlTextReaderConstLocalName(reader);
                    namespaceUri = xmlTextReaderConstNamespaceUri(reader);
                    result = xmlTextReaderGetAttributeNs(reader, localName,
                                                         namespaceUri);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_GET_REMAINDER:
                    startOp("GetRemainder");
                    if (doc == NULL)
                        doc = xmlTextReaderCurrentDoc(reader);
                    xmlFreeParserInputBuffer(xmlTextReaderGetRemainder(reader));
                    break;
    
                case OP_LOOKUP_NAMESPACE: {
                    const xmlChar *prefix = xmlTextReaderConstPrefix(reader);
                    xmlChar *result;
    
                    startOp("LookupNamespace");
                    result = xmlTextReaderLookupNamespace(reader, prefix);
                    FREE_STRING(result);
                    break;
                }
    
                case OP_MOVE_TO_ATTRIBUTE_NO: {
                    int no = READ_BYTE();
    
                    startOp("MoveToAttributeNo");
                    xmlTextReaderMoveToAttributeNo(reader, no);
                    break;
                }
    
                case OP_MOVE_TO_ATTRIBUTE: {
                    const xmlChar *name = xmlTextReaderConstName(reader);
    
                    startOp("MoveToAttribute");
                    xmlTextReaderMoveToAttribute(reader, name);
                    break;
                }
    
                case OP_MOVE_TO_ATTRIBUTE_NS: {
                    const xmlChar *localName, *namespaceUri;
    
                    startOp("MoveToAttributeNs");
                    localName = xmlTextReaderConstLocalName(reader);
                    namespaceUri = xmlTextReaderConstNamespaceUri(reader);
                    xmlTextReaderMoveToAttributeNs(reader, localName,
                                                   namespaceUri);
                    break;
                }
    
                case OP_MOVE_TO_FIRST_ATTRIBUTE:
                    startOp("MoveToFirstAttribute");
                    xmlTextReaderMoveToFirstAttribute(reader);
                    break;
    
                case OP_MOVE_TO_NEXT_ATTRIBUTE:
                    startOp("MoveToNextAttribute");
                    xmlTextReaderMoveToNextAttribute(reader);
                    break;
    
                case OP_MOVE_TO_ELEMENT:
                    startOp("MoveToElement");
                    xmlTextReaderMoveToElement(reader);
                    break;
    
                case OP_NORMALIZATION:
                    startOp("Normalization");
                    xmlTextReaderNormalization(reader);
                    break;
    
                case OP_CONST_ENCODING:
                    startOp("ConstEncoding");
                    xmlTextReaderConstEncoding(reader);
                    break;
    
                case OP_GET_PARSER_PROP: {
                    int prop = READ_BYTE();
    
                    startOp("GetParserProp");
                    xmlTextReaderGetParserProp(reader, prop);
                    break;
                }
    
                case OP_CURRENT_NODE:
                    startOp("CurrentNode");
                    xmlTextReaderCurrentNode(reader);
                    break;
    
                case OP_GET_PARSER_LINE_NUMBER:
                    startOp("GetParserLineNumber");
                    xmlTextReaderGetParserLineNumber(reader);
                    break;
    
                case OP_GET_PARSER_COLUMN_NUMBER:
                    startOp("GetParserColumnNumber");
                    xmlTextReaderGetParserColumnNumber(reader);
                    break;
    
                case OP_PRESERVE:
                    startOp("Preserve");
                    xmlTextReaderPreserve(reader);
                    break;
    
                case OP_CURRENT_DOC: {
                    xmlDocPtr result;
    
                    startOp("CurrentDoc");
                    result = xmlTextReaderCurrentDoc(reader);
                    if (doc == NULL)
                        doc = result;
                    break;
                }
    
                case OP_EXPAND:
                    startOp("Expand");
                    xmlTextReaderExpand(reader);
                    break;
    
                case OP_NEXT:
                    startOp("Next");
                    xmlTextReaderNext(reader);
                    break;
    
                case OP_NEXT_SIBLING:
                    startOp("NextSibling");
                    xmlTextReaderNextSibling(reader);
                    break;
    
                case OP_IS_VALID:
                    startOp("IsValid");
                    xmlTextReaderIsValid(reader);
                    break;
    
                case OP_CONST_XML_VERSION:
                    startOp("ConstXmlVersion");
                    xmlTextReaderConstXmlVersion(reader);
                    break;
    
                case OP_STANDALONE:
                    startOp("Standalone");
                    xmlTextReaderStandalone(reader);
                    break;
    
                case OP_BYTE_CONSUMED:
                    startOp("ByteConsumed");
                    xmlTextReaderByteConsumed(reader);
                    oomReport = -1;
                    break;
            }
    
            if (totalStringSize > docSize * 2)
                break;
        }
    
        error = xmlTextReaderGetLastError(reader);
        if (error->code == XML_ERR_NO_MEMORY)
            oomReport = 1;
        xmlFuzzCheckMallocFailure("reader", oomReport);
    
        xmlFreeTextReader(reader);
    
        if (doc != NULL)
            xmlFreeDoc(doc);
    
    exit:
        xmlFuzzMemSetLimit(0);
        xmlFuzzDataCleanup();
        xmlResetLastError();
        return(0);
    }