diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-11-17 20:58:44 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-11-17 20:58:44 (GMT) |
commit | 4f65b25b474bf534e40c3d3aa47d43e8457fcc9a (patch) | |
tree | 21aab4f800fd8a5046a929b3243edf9d461917d5 /libxml2/testOOM.c | |
parent | 5720be2a1ff34bf88992db24716f1e489a745e01 (diff) | |
parent | 4464fd97bf7e813b5badf1937e59f6fb5d2be646 (diff) | |
download | blt-4f65b25b474bf534e40c3d3aa47d43e8457fcc9a.zip blt-4f65b25b474bf534e40c3d3aa47d43e8457fcc9a.tar.gz blt-4f65b25b474bf534e40c3d3aa47d43e8457fcc9a.tar.bz2 |
Merge commit '4464fd97bf7e813b5badf1937e59f6fb5d2be646' as 'libxml2'
Diffstat (limited to 'libxml2/testOOM.c')
-rw-r--r-- | libxml2/testOOM.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/libxml2/testOOM.c b/libxml2/testOOM.c new file mode 100644 index 0000000..9ff13f2 --- /dev/null +++ b/libxml2/testOOM.c @@ -0,0 +1,377 @@ +/* + * 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> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <libxml/xmlreader.h> + +#include "testOOMlib.h" + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#define EXIT_OOM 2 + +int error = FALSE; +int errcount = 0; +int noent = 0; +int count = 0; +int valid = 0; +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"}; + +/* not using xmlBuff here because I don't want those + * 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; + unsigned int ix; + 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); + } +} + + +static void usage(const char *progname) { + printf("Usage : %s [options] XMLfiles ...\n", progname); + printf("\tParse 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"); + printf("\t --show: display the error messages encountered\n"); + exit(1); +} +static unsigned int elem, attrs, chars; + +static int processNode (xmlTextReaderPtr reader, void *data) +{ + struct buffer *buff = data; + int type; + + type = xmlTextReaderNodeType(reader); + if (count) { + if (type == 1) { + elem++; + attrs += xmlTextReaderAttributeCount(reader); + } else if (type == 3) { + const xmlChar *txt; + txt = xmlTextReaderConstValue(reader); + if (txt != NULL) + chars += xmlStrlen (txt); + else + return FALSE; + } + } + + if (buff != NULL) { + int ret; + const char *s; + + buffer_add_string (buff, elementNames[type]); + + if (type == 1) { + s = (const char *)xmlTextReaderConstName (reader); + if (s == NULL) return FALSE; + buffer_add_string (buff, s); + while ((ret = xmlTextReaderMoveToNextAttribute (reader)) == 1) { + s = (const char *)xmlTextReaderConstName (reader); + if (s == NULL) return FALSE; + buffer_add_string (buff, s); + buffer_add_char (buff, '='); + s = (const char *)xmlTextReaderConstValue (reader); + if (s == NULL) return FALSE; + buffer_add_string (buff, s); + } + if (ret == -1) return FALSE; + } + else if (type == 3) { + s = (const char *)xmlTextReaderConstValue (reader); + if (s == NULL) return FALSE; + buffer_add_string (buff, s); + } + } + + return TRUE; +} + + +struct file_params { + const char *filename; + struct buffer *verif_buff; +}; + +static void +error_func (void *data ATTRIBUTE_UNUSED, xmlErrorPtr err) +{ + + errcount++; + if (err->level == XML_ERR_ERROR || + err->level == XML_ERR_FATAL) + error = TRUE; + if (showErrs) { + printf("%3d line %d: %s\n", error, err->line, err->message); + } +} + +static int +check_load_file_memory_func (void *data) +{ + struct file_params *p = data; + struct buffer *b; + xmlTextReaderPtr reader; + int ret, status, first_run; + + if (count) { + elem = 0; + attrs = 0; + chars = 0; + } + + first_run = p->verif_buff == NULL; + status = TRUE; + 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; + + xmlTextReaderSetStructuredErrorHandler (reader, error_func, NULL); + xmlSetStructuredErrorFunc(NULL, error_func); + + if (valid) { + if (xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1) == -1) + goto out; + } + + /* + * Process all nodes in sequence + */ + while ((ret = xmlTextReaderRead(reader)) == 1) { + if (!processNode(reader, b)) + goto out; + } + if (ret == -1) + goto out; + + if (error) { + fprintf (stdout, "error handler was called but parse completed successfully (last error #%d)\n", errcount); + 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"); + } + } + + if (count) + { + fprintf (stdout, "# %s: %u elems, %u attrs, %u chars %s\n", + p->filename, elem, attrs, chars, + status ? "ok" : "wrong"); + } + + out: + if (first_run) + p->verif_buff = b; + else + buffer_free (b); + if (reader) + xmlFreeTextReader (reader); + return status; +} + +int main(int argc, char **argv) { + int i; + int files = 0; + + if (argc <= 1) { + usage(argv[0]); + return(1); + } + LIBXML_TEST_VERSION; + + xmlMemSetup (test_free, + test_malloc, + test_realloc, + test_strdup); + + xmlInitParser(); + + for (i = 1; i < argc ; i++) { + if ((!strcmp(argv[i], "-count")) || (!strcmp(argv[i], "--count"))) + count++; + else if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid"))) + valid++; + else if ((!strcmp(argv[i], "-noent")) || + (!strcmp(argv[i], "--noent"))) + noent++; + else if ((!strcmp(argv[i], "-show")) || + (!strcmp(argv[i], "--show"))) + showErrs++; + } + if (noent != 0) + xmlSubstituteEntitiesDefault(1); + for (i = 1; i < argc ; i++) { + if (argv[i][0] != '-') { + struct file_params p; + p.filename = argv[i]; + p.verif_buff = NULL; + + if (!test_oom_handling (check_load_file_memory_func, + &p)) { + fprintf (stdout, "Failed!\n"); + return 1; + } + + buffer_free (p.verif_buff); + xmlCleanupParser(); + + if (test_get_malloc_blocks_outstanding () > 0) { + fprintf (stdout, "%d blocks leaked\n", + test_get_malloc_blocks_outstanding ()); + xmlMemoryDump(); + return 1; + } + + files ++; + } + } + xmlMemoryDump(); + + return 0; +} |