2023-03-12 18:15:54 +03:00
/*
* valid . c : a libFuzzer target to test DTD validation .
*
* 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 "fuzz.h"
int
LLVMFuzzerInitialize ( int * argc ATTRIBUTE_UNUSED ,
char * * * argv ATTRIBUTE_UNUSED ) {
xmlFuzzMemSetup ( ) ;
xmlInitParser ( ) ;
# ifdef LIBXML_CATALOG_ENABLED
xmlInitializeCatalog ( ) ;
2024-01-04 17:18:14 +03:00
xmlCatalogSetDefaults ( XML_CATA_ALLOW_NONE ) ;
2023-03-12 18:15:54 +03:00
# endif
xmlSetGenericErrorFunc ( NULL , xmlFuzzErrorFunc ) ;
xmlSetExternalEntityLoader ( xmlFuzzEntityLoader ) ;
return 0 ;
}
int
LLVMFuzzerTestOneInput ( const char * data , size_t size ) {
2023-12-10 20:32:21 +03:00
xmlParserCtxtPtr ctxt ;
2023-03-12 18:15:54 +03:00
xmlDocPtr doc ;
xmlValidCtxtPtr vctxt ;
const char * docBuffer , * docUrl ;
2023-09-21 14:05:49 +03:00
size_t maxAlloc , docSize ;
2023-03-12 18:15:54 +03:00
int opts ;
xmlFuzzDataInit ( data , size ) ;
opts = ( int ) xmlFuzzReadInt ( 4 ) ;
opts & = ~ XML_PARSE_XINCLUDE ;
opts | = XML_PARSE_DTDVALID ;
2023-12-10 20:32:21 +03:00
maxAlloc = xmlFuzzReadInt ( 4 ) % ( size + 100 ) ;
2023-03-12 18:15:54 +03:00
xmlFuzzReadEntities ( ) ;
docBuffer = xmlFuzzMainEntity ( & docSize ) ;
docUrl = xmlFuzzMainUrl ( ) ;
if ( docBuffer = = NULL )
goto exit ;
/* Pull parser */
xmlFuzzMemSetLimit ( maxAlloc ) ;
2023-12-10 20:32:21 +03:00
ctxt = xmlNewParserCtxt ( ) ;
if ( ctxt ! = NULL ) {
doc = xmlCtxtReadMemory ( ctxt , docBuffer , docSize , docUrl , NULL , opts ) ;
xmlFuzzCheckMallocFailure ( " xmlCtxtReadMemory " ,
ctxt - > errNo = = XML_ERR_NO_MEMORY ) ;
xmlFreeDoc ( doc ) ;
xmlFreeParserCtxt ( ctxt ) ;
}
2023-03-12 18:15:54 +03:00
/* Post validation */
xmlFuzzMemSetLimit ( maxAlloc ) ;
2023-12-10 20:32:21 +03:00
doc = xmlReadMemory ( docBuffer , docSize , docUrl , NULL ,
opts & ~ XML_PARSE_DTDVALID ) ;
2023-03-12 18:15:54 +03:00
vctxt = xmlNewValidCtxt ( ) ;
xmlValidateDocument ( vctxt , doc ) ;
xmlFreeValidCtxt ( vctxt ) ;
xmlFreeDoc ( doc ) ;
/* Push parser */
2023-09-21 14:05:49 +03:00
# ifdef LIBXML_PUSH_ENABLED
{
static const size_t maxChunkSize = 128 ;
size_t consumed , chunkSize ;
xmlFuzzMemSetLimit ( maxAlloc ) ;
ctxt = xmlCreatePushParserCtxt ( NULL , NULL , NULL , 0 , docUrl ) ;
2023-12-10 20:32:21 +03:00
if ( ctxt ! = NULL ) {
xmlCtxtUseOptions ( ctxt , opts ) ;
for ( consumed = 0 ; consumed < docSize ; consumed + = chunkSize ) {
chunkSize = docSize - consumed ;
if ( chunkSize > maxChunkSize )
chunkSize = maxChunkSize ;
xmlParseChunk ( ctxt , docBuffer + consumed , chunkSize , 0 ) ;
}
2023-03-12 18:15:54 +03:00
2023-12-10 20:32:21 +03:00
xmlParseChunk ( ctxt , NULL , 0 , 1 ) ;
xmlFuzzCheckMallocFailure ( " xmlParseChunk " ,
ctxt - > errNo = = XML_ERR_NO_MEMORY ) ;
xmlFreeDoc ( ctxt - > myDoc ) ;
xmlFreeParserCtxt ( ctxt ) ;
}
2023-03-12 18:15:54 +03:00
}
2023-09-21 14:05:49 +03:00
# endif
2023-03-12 18:15:54 +03:00
/* Reader */
2023-09-21 14:05:49 +03:00
# ifdef LIBXML_READER_ENABLED
{
xmlTextReaderPtr reader ;
2023-12-10 20:32:21 +03:00
const xmlError * error ;
2023-10-14 23:48:12 +03:00
int j ;
2023-09-21 14:05:49 +03:00
xmlFuzzMemSetLimit ( maxAlloc ) ;
reader = xmlReaderForMemory ( docBuffer , docSize , NULL , NULL , opts ) ;
2023-12-10 20:32:21 +03:00
if ( reader ! = NULL ) {
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 ) ;
}
2023-09-21 14:05:49 +03:00
}
2023-03-12 18:15:54 +03:00
}
2023-12-10 20:32:21 +03:00
for ( j = 0 ; j < 10 ; j + + )
xmlTextReaderRead ( reader ) ;
error = xmlTextReaderGetLastError ( reader ) ;
xmlFuzzCheckMallocFailure ( " xmlTextReaderRead " ,
error - > code = = XML_ERR_NO_MEMORY ) ;
xmlFreeTextReader ( reader ) ;
2023-03-12 18:15:54 +03:00
}
}
2023-09-21 14:05:49 +03:00
# endif
2023-03-12 18:15:54 +03:00
exit :
xmlFuzzMemSetLimit ( 0 ) ;
xmlFuzzDataCleanup ( ) ;
xmlResetLastError ( ) ;
return ( 0 ) ;
}