2003-04-24 20:06:47 +04:00
/*
* testOOM . c : Test out - of - memory handling
*
* See Copyright for the status of this software .
*
* hp @ redhat . com
*/
# include "libxml.h"
# include <string.h>
# include <stdarg.h>
2022-03-02 02:29:17 +03:00
# include <stdlib.h>
2003-04-24 20:06:47 +04:00
# include <libxml/xmlreader.h>
# include "testOOMlib.h"
# ifndef TRUE
# define TRUE (1)
# endif
# ifndef FALSE
# define FALSE (0)
# endif
2004-07-29 11:07:16 +04:00
# define EXIT_OOM 2
2003-04-24 20:06:47 +04:00
2004-07-31 20:24:01 +04:00
int error = FALSE ;
int errcount = 0 ;
2003-04-24 20:06:47 +04:00
int noent = 0 ;
int count = 0 ;
int valid = 0 ;
2004-07-29 11:07:16 +04:00
int showErrs = 0 ;
/*
* Since we are using the xmlTextReader functions , we set up
* strings for the element types to help in debugging any error
* output
*/
const char * elementNames [ ] = {
" XML_READER_TYPE_NONE " ,
" XML_READER_TYPE_ELEMENT " ,
" XML_READER_TYPE_ATTRIBUTE " ,
" XML_READER_TYPE_TEXT " ,
" XML_READER_TYPE_CDATA " ,
" XML_READER_TYPE_ENTITY_REFERENCE " ,
" XML_READER_TYPE_ENTITY " ,
" XML_READER_TYPE_PROCESSING_INSTRUCTION " ,
" XML_READER_TYPE_COMMENT " ,
" XML_READER_TYPE_DOCUMENT " ,
" XML_READER_TYPE_DOCUMENT_TYPE " ,
" XML_READER_TYPE_DOCUMENT_FRAGMENT " ,
" XML_READER_TYPE_NOTATION " ,
" XML_READER_TYPE_WHITESPACE " ,
" XML_READER_TYPE_SIGNIFICANT_WHITESPACE " ,
" XML_READER_TYPE_END_ELEMENT " ,
" XML_READER_TYPE_END_ENTITY " ,
" XML_READER_TYPE_XML_DECLARATION " } ;
2012-09-11 09:26:36 +04:00
/* not using xmlBuff here because I don't want those
2004-07-29 11:07:16 +04:00
* mallocs to interfere */
struct buffer {
char * str ;
size_t len ;
size_t max ;
} ;
static struct buffer * buffer_create ( size_t init_len )
{
struct buffer * b ;
b = malloc ( sizeof * b ) ;
if ( b = = NULL )
exit ( EXIT_OOM ) ;
if ( init_len ) {
b - > str = malloc ( init_len ) ;
if ( b - > str = = NULL )
exit ( EXIT_OOM ) ;
}
else
b - > str = NULL ;
b - > len = 0 ;
b - > max = init_len ;
return b ;
}
static void buffer_free ( struct buffer * b )
{
free ( b - > str ) ;
free ( b ) ;
}
static size_t buffer_get_length ( struct buffer * b )
{
return b - > len ;
}
static void buffer_expand ( struct buffer * b , size_t min )
{
void * new_str ;
size_t new_size = b - > max ? b - > max : 512 ;
while ( new_size < b - > len + min )
new_size * = 2 ;
if ( new_size > b - > max ) {
new_str = realloc ( b - > str , new_size ) ;
if ( new_str = = NULL )
exit ( EXIT_OOM ) ;
b - > str = new_str ;
b - > max = new_size ;
}
}
static void buffer_add_char ( struct buffer * b , char c )
{
buffer_expand ( b , 1 ) ;
b - > str [ b - > len ] = c ;
b - > len + = 1 ;
}
static void buffer_add_string ( struct buffer * b , const char * s )
{
size_t size = strlen ( s ) + 1 ;
2004-07-31 20:24:01 +04:00
unsigned int ix ;
2004-07-29 11:07:16 +04:00
for ( ix = 0 ; ix < size - 1 ; ix + + ) {
if ( s [ ix ] < 0x20 )
printf ( " binary data [0x%02x]? \n " , ( unsigned char ) s [ ix ] ) ;
}
buffer_expand ( b , size ) ;
strcpy ( b - > str + b - > len , s ) ;
b - > str [ b - > len + size - 1 ] = ' \n ' ; /* replace string term with newline */
b - > len + = size ;
}
static int buffer_equal ( struct buffer * b1 , struct buffer * b2 )
{
return ( b1 - > len = = b2 - > len & &
( b1 - > len = = 0 | | ( memcmp ( b1 - > str , b2 - > str , b1 - > len ) = = 0 ) ) ) ;
}
static void buffer_dump ( struct buffer * b , const char * fname )
{
FILE * f = fopen ( fname , " wb " ) ;
if ( f ! = NULL ) {
fwrite ( b - > str , 1 , b - > len , f ) ;
fclose ( f ) ;
}
}
2003-04-24 20:06:47 +04:00
static void usage ( const char * progname ) {
printf ( " Usage : %s [options] XMLfiles ... \n " , progname ) ;
printf ( " \t Parse the XML files using the xmlTextReader API \n " ) ;
printf ( " \t --count: count the number of attribute and elements \n " ) ;
printf ( " \t --valid: validate the document \n " ) ;
2004-07-29 11:07:16 +04:00
printf ( " \t --show: display the error messages encountered \n " ) ;
2003-04-24 20:06:47 +04:00
exit ( 1 ) ;
}
2004-07-28 11:40:12 +04:00
static unsigned int elem , attrs , chars ;
2003-04-24 20:06:47 +04:00
2004-07-29 11:07:16 +04:00
static int processNode ( xmlTextReaderPtr reader , void * data )
{
struct buffer * buff = data ;
2003-04-24 20:06:47 +04:00
int type ;
type = xmlTextReaderNodeType ( reader ) ;
if ( count ) {
if ( type = = 1 ) {
elem + + ;
attrs + = xmlTextReaderAttributeCount ( reader ) ;
2004-07-28 11:40:12 +04:00
} else if ( type = = 3 ) {
const xmlChar * txt ;
txt = xmlTextReaderConstValue ( reader ) ;
if ( txt ! = NULL )
chars + = xmlStrlen ( txt ) ;
else
return FALSE ;
2003-04-24 20:06:47 +04:00
}
}
2004-07-29 11:07:16 +04:00
if ( buff ! = NULL ) {
int ret ;
const char * s ;
buffer_add_string ( buff , elementNames [ type ] ) ;
if ( type = = 1 ) {
2004-07-31 20:24:01 +04:00
s = ( const char * ) xmlTextReaderConstName ( reader ) ;
2004-07-29 11:07:16 +04:00
if ( s = = NULL ) return FALSE ;
buffer_add_string ( buff , s ) ;
while ( ( ret = xmlTextReaderMoveToNextAttribute ( reader ) ) = = 1 ) {
2004-07-31 20:24:01 +04:00
s = ( const char * ) xmlTextReaderConstName ( reader ) ;
2004-07-29 11:07:16 +04:00
if ( s = = NULL ) return FALSE ;
buffer_add_string ( buff , s ) ;
buffer_add_char ( buff , ' = ' ) ;
2004-07-31 20:24:01 +04:00
s = ( const char * ) xmlTextReaderConstValue ( reader ) ;
2004-07-29 11:07:16 +04:00
if ( s = = NULL ) return FALSE ;
2012-09-11 09:26:36 +04:00
buffer_add_string ( buff , s ) ;
2004-07-29 11:07:16 +04:00
}
if ( ret = = - 1 ) return FALSE ;
}
else if ( type = = 3 ) {
2004-07-31 20:24:01 +04:00
s = ( const char * ) xmlTextReaderConstValue ( reader ) ;
2004-07-29 11:07:16 +04:00
if ( s = = NULL ) return FALSE ;
buffer_add_string ( buff , s ) ;
}
}
2003-04-24 20:06:47 +04:00
return TRUE ;
}
2004-07-28 11:40:12 +04:00
struct file_params {
2004-07-29 11:07:16 +04:00
const char * filename ;
struct buffer * verif_buff ;
2004-07-28 11:40:12 +04:00
} ;
2004-07-29 11:07:16 +04:00
static void
2004-07-31 20:24:01 +04:00
error_func ( void * data ATTRIBUTE_UNUSED , xmlErrorPtr err )
2004-07-29 11:07:16 +04:00
{
2004-07-31 20:24:01 +04:00
errcount + + ;
2004-07-29 11:07:16 +04:00
if ( err - > level = = XML_ERR_ERROR | |
err - > level = = XML_ERR_FATAL )
2004-07-31 20:24:01 +04:00
error = TRUE ;
2004-07-29 11:07:16 +04:00
if ( showErrs ) {
2004-07-31 20:24:01 +04:00
printf ( " %3d line %d: %s \n " , error , err - > line , err - > message ) ;
2004-07-29 11:07:16 +04:00
}
}
2003-04-24 20:06:47 +04:00
static int
check_load_file_memory_func ( void * data )
{
2004-07-28 11:40:12 +04:00
struct file_params * p = data ;
2004-07-29 11:07:16 +04:00
struct buffer * b ;
2003-04-24 20:06:47 +04:00
xmlTextReaderPtr reader ;
2004-07-31 20:24:01 +04:00
int ret , status , first_run ;
2003-04-24 20:06:47 +04:00
if ( count ) {
2004-07-29 11:07:16 +04:00
elem = 0 ;
attrs = 0 ;
chars = 0 ;
2003-04-24 20:06:47 +04:00
}
2004-07-29 11:07:16 +04:00
first_run = p - > verif_buff = = NULL ;
2004-07-28 11:40:12 +04:00
status = TRUE ;
2004-07-29 11:07:16 +04:00
error = FALSE ;
if ( first_run )
b = buffer_create ( 0 ) ;
else
b = buffer_create ( buffer_get_length ( p - > verif_buff ) ) ;
reader = xmlNewTextReaderFilename ( p - > filename ) ;
if ( reader = = NULL )
goto out ;
2004-07-28 11:40:12 +04:00
2004-07-31 20:24:01 +04:00
xmlTextReaderSetStructuredErrorHandler ( reader , error_func , NULL ) ;
xmlSetStructuredErrorFunc ( NULL , error_func ) ;
2004-07-29 11:07:16 +04:00
if ( valid ) {
if ( xmlTextReaderSetParserProp ( reader , XML_PARSER_VALIDATE , 1 ) = = - 1 )
goto out ;
}
2012-09-11 09:26:36 +04:00
2004-07-29 11:07:16 +04:00
/*
* Process all nodes in sequence
*/
while ( ( ret = xmlTextReaderRead ( reader ) ) = = 1 ) {
if ( ! processNode ( reader , b ) )
goto out ;
2003-04-24 20:06:47 +04:00
}
2004-07-29 11:07:16 +04:00
if ( ret = = - 1 )
goto out ;
if ( error ) {
2004-07-31 20:24:01 +04:00
fprintf ( stdout , " error handler was called but parse completed successfully (last error #%d) \n " , errcount ) ;
2004-07-29 11:07:16 +04:00
return FALSE ;
}
/*
* Done , cleanup and status
*/
if ( ! first_run ) {
status = buffer_equal ( p - > verif_buff , b ) ;
if ( ! status ) {
buffer_dump ( p - > verif_buff , " .OOM.verif_buff " ) ;
buffer_dump ( b , " .OOM.buff " ) ;
}
}
2012-09-11 09:26:36 +04:00
2004-07-29 11:07:16 +04:00
if ( count )
{
fprintf ( stdout , " # %s: %u elems, %u attrs, %u chars %s \n " ,
p - > filename , elem , attrs , chars ,
status ? " ok " : " wrong " ) ;
}
2004-07-28 11:40:12 +04:00
out :
2004-07-29 11:07:16 +04:00
if ( first_run )
p - > verif_buff = b ;
else
buffer_free ( b ) ;
2004-07-28 11:40:12 +04:00
if ( reader )
2004-07-29 11:07:16 +04:00
xmlFreeTextReader ( reader ) ;
2004-07-28 11:40:12 +04:00
return status ;
2003-04-24 20:06:47 +04:00
}
int main ( int argc , char * * argv ) {
int i ;
int files = 0 ;
if ( argc < = 1 ) {
usage ( argv [ 0 ] ) ;
return ( 1 ) ;
}
2012-09-11 09:26:36 +04:00
LIBXML_TEST_VERSION ;
2003-04-24 20:06:47 +04:00
xmlMemSetup ( test_free ,
test_malloc ,
test_realloc ,
test_strdup ) ;
2004-07-29 11:07:16 +04:00
xmlInitParser ( ) ;
2003-04-24 20:06:47 +04:00
for ( i = 1 ; i < argc ; i + + ) {
2004-07-29 11:07:16 +04:00
if ( ( ! strcmp ( argv [ i ] , " -count " ) ) | | ( ! strcmp ( argv [ i ] , " --count " ) ) )
2003-04-24 20:06:47 +04:00
count + + ;
else if ( ( ! strcmp ( argv [ i ] , " -valid " ) ) | | ( ! strcmp ( argv [ i ] , " --valid " ) ) )
valid + + ;
else if ( ( ! strcmp ( argv [ i ] , " -noent " ) ) | |
( ! strcmp ( argv [ i ] , " --noent " ) ) )
noent + + ;
2004-07-29 11:07:16 +04:00
else if ( ( ! strcmp ( argv [ i ] , " -show " ) ) | |
( ! strcmp ( argv [ i ] , " --show " ) ) )
showErrs + + ;
2003-04-24 20:06:47 +04:00
}
if ( noent ! = 0 )
xmlSubstituteEntitiesDefault ( 1 ) ;
for ( i = 1 ; i < argc ; i + + ) {
if ( argv [ i ] [ 0 ] ! = ' - ' ) {
2004-07-28 11:40:12 +04:00
struct file_params p ;
p . filename = argv [ i ] ;
2004-07-29 11:07:16 +04:00
p . verif_buff = NULL ;
2003-04-24 20:06:47 +04:00
if ( ! test_oom_handling ( check_load_file_memory_func ,
2004-07-28 11:40:12 +04:00
& p ) ) {
2004-07-29 11:07:16 +04:00
fprintf ( stdout , " Failed! \n " ) ;
return 1 ;
2003-04-24 20:06:47 +04:00
}
2004-07-29 11:07:16 +04:00
buffer_free ( p . verif_buff ) ;
2003-04-24 20:06:47 +04:00
xmlCleanupParser ( ) ;
if ( test_get_malloc_blocks_outstanding ( ) > 0 ) {
2004-07-29 11:07:16 +04:00
fprintf ( stdout , " %d blocks leaked \n " ,
2003-04-24 20:06:47 +04:00
test_get_malloc_blocks_outstanding ( ) ) ;
xmlMemoryDump ( ) ;
2004-07-29 11:07:16 +04:00
return 1 ;
2003-04-24 20:06:47 +04:00
}
2012-09-11 09:26:36 +04:00
2003-04-24 20:06:47 +04:00
files + + ;
}
}
xmlMemoryDump ( ) ;
2004-07-29 11:07:16 +04:00
return 0 ;
2003-04-24 20:06:47 +04:00
}