integrated the Out Of Memory test from Havoc Pennington #109368 a lot of

* Makefile.am testOOM.c testOOMlib.[ch] : integrated the Out Of
  Memory test from Havoc Pennington #109368
* SAX.c parser.c parserInternals.c tree.c uri.c valid.c
  xmlmemory.c xmlreader.c xmlregexp.c include/libxml/tree.h
  include/libxml/parser.h: a lot of memory allocation cleanups
  based on the results of the OOM testing
* check-relaxng-test-suite2.py: seems I forgot to commit the
  script.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 0558bf0..187c801 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Thu Apr 24 18:01:46 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+	* Makefile.am testOOM.c testOOMlib.[ch] : integrated the Out Of
+	  Memory test from Havoc Pennington #109368
+	* SAX.c parser.c parserInternals.c tree.c uri.c valid.c
+	  xmlmemory.c xmlreader.c xmlregexp.c include/libxml/tree.h
+	  include/libxml/parser.h: a lot of memory allocation cleanups
+	  based on the results of the OOM testing
+	* check-relaxng-test-suite2.py: seems I forgot to commit the
+	  script.
+
 Wed Apr 23 17:16:41 CEST 2003 Daniel Veillard <daniel@veillard.com>
 
 	* xmlschemastypes.c: trivial fix for 109774 removing a warning
diff --git a/Makefile.am b/Makefile.am
index 9d32c31..7242f99 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -116,6 +116,11 @@
 testReader_DEPENDENCIES = $(DEPS)
 testReader_LDADD= $(LDADDS)
 
+testOOM_SOURCES=testOOM.c testOOMlib.h testOOMlib.c
+testOOM_LDFLAGS = 
+testOOM_DEPENDENCIES = $(DEPS)
+testOOM_LDADD= $(LDADDS)
+
 check-local: tests
 
 testall : tests SVGtests SAXtests
diff --git a/SAX.c b/SAX.c
index 6bbb401..df30c62 100644
--- a/SAX.c
+++ b/SAX.c
@@ -232,6 +232,8 @@
 		ctxt->sax->error(ctxt->userData, 
 		     "externalSubset: out of memory\n");
 	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
 	    ctxt->input = oldinput;
 	    ctxt->inputNr = oldinputNr;
 	    ctxt->inputMax = oldinputMax;
@@ -745,12 +747,25 @@
 	    "SAX.startDocument()\n");
 #endif
     if (ctxt->html) {
-	if (ctxt->myDoc == NULL)
 #ifdef LIBXML_HTML_ENABLED
+	if (ctxt->myDoc == NULL)
 	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
+	if (ctxt->myDoc == NULL) {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "SAX.startDocument(): out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
+	    return;
+	}
 #else
         xmlGenericError(xmlGenericErrorContext,
 		"libxml2 built without HTML support\n");
+	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+	return;
 #endif
     } else {
 	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
@@ -760,6 +775,14 @@
 	    else
 		doc->encoding = NULL;
 	    doc->standalone = ctxt->standalone;
+	} else {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "SAX.startDocument(): out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
+	    return;
 	}
     }
     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
@@ -839,6 +862,17 @@
      * Split the full name into a namespace prefix and the tag name
      */
     name = xmlSplitQName(ctxt, fullname, &ns);
+    if (name == NULL) {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt->userData, 
+		 "SAX.startElement(): out of memory\n");
+	ctxt->errNo = XML_ERR_NO_MEMORY;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+	if (ns != NULL)
+	    xmlFree(ns);
+	return;
+    }
 
     /*
      * Do the last stage of the attribute normalization
@@ -921,6 +955,18 @@
 	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
 		                          0,0,0);
 	    ctxt->depth--;
+	    if (val == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.startElement(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	        xmlFree(ns);
+		if (name != NULL) 
+		    xmlFree(name);
+		return;
+	    }
 	} else {
 	    val = (xmlChar *) value;
 	}
@@ -1200,14 +1246,19 @@
 					     attr->elem, attr->name,
 					     attr->prefix);
 		    if ((tst == attr) || (tst == NULL)) {
+		        xmlChar fn[50];
 			xmlChar *fulln;
 
-			if (attr->prefix != NULL) {
-			    fulln = xmlStrdup(attr->prefix);
-			    fulln = xmlStrcat(fulln, BAD_CAST ":");
-			    fulln = xmlStrcat(fulln, attr->name);
-			} else {
-			    fulln = xmlStrdup(attr->name);
+                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
+			if (fulln == NULL) {
+			    if ((ctxt->sax != NULL) &&
+			        (ctxt->sax->error != NULL))
+				ctxt->sax->error(ctxt->userData, 
+				     "SAX.startElement(): out of memory\n");
+			    ctxt->errNo = XML_ERR_NO_MEMORY;
+			    ctxt->instate = XML_PARSER_EOF;
+			    ctxt->disableSAX = 1;
+			    return;
 			}
 
 			/*
@@ -1229,7 +1280,8 @@
 			    my_attribute(ctxt, fulln, attr->defaultValue,
 			                 prefix);
 			}
-			xmlFree(fulln);
+			if ((fulln != fn) && (fulln != attr->name))
+			    xmlFree(fulln);
 		    }
 		}
 	    }
@@ -1301,7 +1353,14 @@
      *        an attribute at this level.
      */
     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
-    if (ret == NULL) return;
+    if (ret == NULL) {
+        if (prefix != NULL)
+	    xmlFree(prefix);
+	ctxt->errNo = XML_ERR_NO_MEMORY;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+        return;
+    }
     if (ctxt->myDoc->children == NULL) {
 #ifdef DEBUG_SAX_TREE
 	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
@@ -1587,6 +1646,9 @@
 		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 			ctxt->sax->error(ctxt->userData, 
 			     "SAX.characters(): out of memory\n");
+		    ctxt->errNo = XML_ERR_NO_MEMORY;
+		    ctxt->instate = XML_PARSER_EOF;
+		    ctxt->disableSAX = 1;
 		    return;
 		}
 		ctxt->nodemem = size;
@@ -1596,7 +1658,14 @@
 	    ctxt->nodelen += len;
 	    lastChild->content[ctxt->nodelen] = 0;
 	} else if (coalesceText) {
-	    xmlTextConcat(lastChild, ch, len);
+	    if (xmlTextConcat(lastChild, ch, len)) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.characters(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	    }
 	    if (ctxt->node->children != NULL) {
 		ctxt->nodelen = xmlStrlen(lastChild->content);
 		ctxt->nodemem = ctxt->nodelen + 1;
@@ -1604,10 +1673,19 @@
 	} else {
 	    /* Mixed content, first time */
 	    lastChild = xmlNewTextLen(ch, len);
-	    xmlAddChild(ctxt->node, lastChild);
-	    if (ctxt->node->children != NULL) {
-		ctxt->nodelen = len;
-		ctxt->nodemem = len + 1;
+	    if (lastChild == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.characters(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	    } else {
+		xmlAddChild(ctxt->node, lastChild);
+		if (ctxt->node->children != NULL) {
+		    ctxt->nodelen = len;
+		    ctxt->nodemem = len + 1;
+		}
 	    }
 	}
     }
diff --git a/check-relaxng-test-suite2.py b/check-relaxng-test-suite2.py
new file mode 100755
index 0000000..6a2b6eb
--- /dev/null
+++ b/check-relaxng-test-suite2.py
@@ -0,0 +1,407 @@
+#!/usr/bin/python
+import sys
+import time
+import os
+import string
+import StringIO
+sys.path.append("python")
+import libxml2
+
+# Memory debug specific
+libxml2.debugMemory(1)
+debug = 0
+
+#
+# the testsuite description
+#
+CONF="test/relaxng/testsuite.xml"
+LOG="check-relaxng-test-suite2.log"
+
+log = open(LOG, "w")
+nb_schemas_tests = 0
+nb_schemas_success = 0
+nb_schemas_failed = 0
+nb_instances_tests = 0
+nb_instances_success = 0
+nb_instances_failed = 0
+
+libxml2.lineNumbersDefault(1)
+#
+# Resolver callback
+#
+resources = {}
+def resolver(URL, ID, ctxt):
+    global resources
+
+    if resources.has_key(URL):
+        return(StringIO.StringIO(resources[URL]))
+    log.write("Resolver failure: asked %s\n" % (URL))
+    log.write("resources: %s\n" % (resources))
+    return None
+
+#
+# Load the previous results
+#
+#results = {}
+#previous = {}
+#
+#try:
+#    res = libxml2.parseFile(RES)
+#except:
+#    log.write("Could not parse %s" % (RES))
+    
+#
+# handle a valid instance
+#
+def handle_valid(node, schema):
+    global log
+    global nb_instances_success
+    global nb_instances_failed
+
+    instance = node.prop("dtd")
+    if instance == None:
+        instance = ""
+    child = node.children
+    while child != None:
+        if child.type != 'text':
+	    instance = instance + child.serialize()
+	child = child.next
+
+    mem = libxml2.debugMemory(1);
+    try:
+	doc = libxml2.parseDoc(instance)
+    except:
+        doc = None
+
+    if doc == None:
+        log.write("\nFailed to parse correct instance:\n-----\n")
+	log.write(instance)
+        log.write("\n-----\n")
+	nb_instances_failed = nb_instances_failed + 1
+	return
+
+    if debug:
+        print "instance line %d" % (node.lineNo())
+       
+    try:
+        ctxt = schema.relaxNGNewValidCtxt()
+	ret = doc.relaxNGValidateDoc(ctxt)
+	del ctxt
+    except:
+        ret = -1
+
+    doc.freeDoc()
+    if mem != libxml2.debugMemory(1):
+	print "validating instance %d line %d leaks" % (
+		  nb_instances_tests, node.lineNo())
+
+    if ret != 0:
+        log.write("\nFailed to validate correct instance:\n-----\n")
+	log.write(instance)
+        log.write("\n-----\n")
+	nb_instances_failed = nb_instances_failed + 1
+    else:
+	nb_instances_success = nb_instances_success + 1
+
+#
+# handle an invalid instance
+#
+def handle_invalid(node, schema):
+    global log
+    global nb_instances_success
+    global nb_instances_failed
+
+    instance = node.prop("dtd")
+    if instance == None:
+        instance = ""
+    child = node.children
+    while child != None:
+        if child.type != 'text':
+	    instance = instance + child.serialize()
+	child = child.next
+
+    mem = libxml2.debugMemory(1);
+
+    try:
+	doc = libxml2.parseDoc(instance)
+    except:
+        doc = None
+
+    if doc == None:
+        log.write("\nStrange: failed to parse incorrect instance:\n-----\n")
+	log.write(instance)
+        log.write("\n-----\n")
+	return
+
+    if debug:
+        print "instance line %d" % (node.lineNo())
+       
+    try:
+        ctxt = schema.relaxNGNewValidCtxt()
+	ret = doc.relaxNGValidateDoc(ctxt)
+	del ctxt
+
+    except:
+        ret = -1
+
+    doc.freeDoc()
+    if mem != libxml2.debugMemory(1):
+	print "validating instance %d line %d leaks" % (
+		  nb_instances_tests, node.lineNo())
+    
+    if ret == 0:
+        log.write("\nFailed to detect validation problem in instance:\n-----\n")
+	log.write(instance)
+        log.write("\n-----\n")
+	nb_instances_failed = nb_instances_failed + 1
+    else:
+	nb_instances_success = nb_instances_success + 1
+
+#
+# handle an incorrect test
+#
+def handle_correct(node):
+    global log
+    global nb_schemas_success
+    global nb_schemas_failed
+
+    schema = ""
+    child = node.children
+    while child != None:
+        if child.type != 'text':
+	    schema = schema + child.serialize()
+	child = child.next
+
+    try:
+	rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
+	rngs = rngp.relaxNGParse()
+    except:
+        rngs = None
+    if rngs == None:
+        log.write("\nFailed to compile correct schema:\n-----\n")
+	log.write(schema)
+        log.write("\n-----\n")
+	nb_schemas_failed = nb_schemas_failed + 1
+    else:
+	nb_schemas_success = nb_schemas_success + 1
+    return rngs
+        
+def handle_incorrect(node):
+    global log
+    global nb_schemas_success
+    global nb_schemas_failed
+
+    schema = ""
+    child = node.children
+    while child != None:
+        if child.type != 'text':
+	    schema = schema + child.serialize()
+	child = child.next
+
+    try:
+	rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
+	rngs = rngp.relaxNGParse()
+    except:
+        rngs = None
+    if rngs != None:
+        log.write("\nFailed to detect schema error in:\n-----\n")
+	log.write(schema)
+        log.write("\n-----\n")
+	nb_schemas_failed = nb_schemas_failed + 1
+    else:
+#	log.write("\nSuccess detecting schema error in:\n-----\n")
+#	log.write(schema)
+#	log.write("\n-----\n")
+	nb_schemas_success = nb_schemas_success + 1
+    return None
+
+#
+# resource handling: keep a dictionary of URL->string mappings
+#
+def handle_resource(node, dir):
+    global resources
+
+    try:
+	name = node.prop('name')
+    except:
+        name = None
+
+    if name == None or name == '':
+        log.write("resource has no name")
+	return;
+        
+    if dir != None:
+#        name = libxml2.buildURI(name, dir)
+        name = dir + '/' + name
+
+    res = ""
+    child = node.children
+    while child != None:
+        if child.type != 'text':
+	    res = res + child.serialize()
+	child = child.next
+    resources[name] = res
+
+#
+# dir handling: pseudo directory resources
+#
+def handle_dir(node, dir):
+    try:
+	name = node.prop('name')
+    except:
+        name = None
+
+    if name == None or name == '':
+        log.write("resource has no name")
+	return;
+        
+    if dir != None:
+#        name = libxml2.buildURI(name, dir)
+        name = dir + '/' + name
+
+    dirs = node.xpathEval('dir')
+    for dir in dirs:
+        handle_dir(dir, name)
+    res = node.xpathEval('resource')
+    for r in res:
+        handle_resource(r, name)
+
+#
+# handle a testCase element
+#
+def handle_testCase(node):
+    global nb_schemas_tests
+    global nb_instances_tests
+    global resources
+
+    sections = node.xpathEval('string(section)')
+    log.write("\n    ======== test %d line %d section %s ==========\n" % (
+
+              nb_schemas_tests, node.lineNo(), sections))
+    resources = {}
+    if debug:
+        print "test %d line %d" % (nb_schemas_tests, node.lineNo())
+
+    dirs = node.xpathEval('dir')
+    for dir in dirs:
+        handle_dir(dir, None)
+    res = node.xpathEval('resource')
+    for r in res:
+        handle_resource(r, None)
+
+    tsts = node.xpathEval('incorrect')
+    if tsts != []:
+        if len(tsts) != 1:
+	    print "warning test line %d has more than one <incorrect> example" %(node.lineNo())
+	schema = handle_incorrect(tsts[0])
+    else:
+        tsts = node.xpathEval('correct')
+	if tsts != []:
+	    if len(tsts) != 1:
+		print "warning test line %d has more than one <correct> example"% (node.lineNo())
+	    schema = handle_correct(tsts[0])
+	else:
+	    print "warning <testCase> line %d has no <correct> nor <incorrect> child" % (node.lineNo())
+
+    nb_schemas_tests = nb_schemas_tests + 1;
+    
+    valids = node.xpathEval('valid')
+    invalids = node.xpathEval('invalid')
+    nb_instances_tests = nb_instances_tests + len(valids) + len(invalids)
+    if schema != None:
+        for valid in valids:
+	    handle_valid(valid, schema)
+        for invalid in invalids:
+	    handle_invalid(invalid, schema)
+
+
+#
+# handle a testSuite element
+#
+def handle_testSuite(node, level = 0):
+    global nb_schemas_tests, nb_schemas_success, nb_schemas_failed
+    global nb_instances_tests, nb_instances_success, nb_instances_failed
+    if level >= 1:
+	old_schemas_tests = nb_schemas_tests
+	old_schemas_success = nb_schemas_success
+	old_schemas_failed = nb_schemas_failed
+	old_instances_tests = nb_instances_tests
+	old_instances_success = nb_instances_success
+	old_instances_failed = nb_instances_failed
+
+    docs = node.xpathEval('documentation')
+    authors = node.xpathEval('author')
+    if docs != []:
+        msg = ""
+        for doc in docs:
+	    msg = msg + doc.content + " "
+	if authors != []:
+	    msg = msg + "written by "
+	    for author in authors:
+	        msg = msg + author.content + " "
+	print msg
+    sections = node.xpathEval('section')
+    if sections != [] and level <= 0:
+        msg = ""
+        for section in sections:
+	    msg = msg + section.content + " "
+        print "Tests for section %s" % (msg)
+    for test in node.xpathEval('testCase'):
+        handle_testCase(test)
+    for test in node.xpathEval('testSuite'):
+        handle_testSuite(test, level + 1)
+	        
+
+    if level >= 1 and sections != []:
+        msg = ""
+        for section in sections:
+	    msg = msg + section.content + " "
+        print "Result of tests for section %s" % (msg)
+        if nb_schemas_tests != old_schemas_tests:
+	    print "found %d test schemas: %d success %d failures" % (
+		  nb_schemas_tests - old_schemas_tests,
+		  nb_schemas_success - old_schemas_success,
+		  nb_schemas_failed - old_schemas_failed)
+	if nb_instances_tests != old_instances_tests:
+	    print "found %d test instances: %d success %d failures" % (
+		  nb_instances_tests - old_instances_tests,
+		  nb_instances_success - old_instances_success,
+		  nb_instances_failed - old_instances_failed)
+#
+# Parse the conf file
+#
+libxml2.substituteEntitiesDefault(1);
+testsuite = libxml2.parseFile(CONF)
+
+#
+# Error and warnng callbacks
+#
+def callback(ctx, str):
+    global log
+    log.write("%s%s" % (ctx, str))
+
+libxml2.registerErrorHandler(callback, "")
+
+libxml2.setEntityLoader(resolver)
+root = testsuite.getRootElement()
+if root.name != 'testSuite':
+    print "%s doesn't start with a testSuite element, aborting" % (CONF)
+    sys.exit(1)
+print "Running Relax NG testsuite"
+handle_testSuite(root)
+
+print "\nTOTAL:\nfound %d test schemas: %d success %d failures" % (
+      nb_schemas_tests, nb_schemas_success, nb_schemas_failed)
+print "found %d test instances: %d success %d failures" % (
+      nb_instances_tests, nb_instances_success, nb_instances_failed)
+
+testsuite.freeDoc()
+
+# Memory debug specific
+libxml2.relaxNGCleanupTypes()
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 4578ad9..0a3597e 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -802,7 +802,7 @@
 /*
  * Parser contexts handling.
  */
-void		xmlInitParserCtxt	(xmlParserCtxtPtr ctxt);
+int		xmlInitParserCtxt	(xmlParserCtxtPtr ctxt);
 void		xmlClearParserCtxt	(xmlParserCtxtPtr ctxt);
 void		xmlFreeParserCtxt	(xmlParserCtxtPtr ctxt);
 void		xmlSetupParserForBuffer	(xmlParserCtxtPtr ctxt,
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 60c1d88..c8467e8 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -724,7 +724,7 @@
 void		xmlUnlinkNode		(xmlNodePtr cur);
 xmlNodePtr	xmlTextMerge		(xmlNodePtr first,
 					 xmlNodePtr second);
-void		xmlTextConcat		(xmlNodePtr node,
+int		xmlTextConcat		(xmlNodePtr node,
 					 const xmlChar *content,
 					 int len);
 void		xmlFreeNodeList		(xmlNodePtr cur);
diff --git a/parser.c b/parser.c
index c1ce81e..bb6f5cc 100644
--- a/parser.c
+++ b/parser.c
@@ -1720,6 +1720,8 @@
 
     *prefix = NULL;
 
+    if (cur == NULL) return(NULL);
+
 #ifndef XML_XML_NAMESPACE
     /* xml: prefix is not really a namespace */
     if ((cur[0] == 'x') && (cur[1] == 'm') &&
@@ -1905,6 +1907,14 @@
 	    ctxt->input->cur = in;
 	    ctxt->nbChars += count;
 	    ctxt->input->col += count;
+	    if (ret == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "XML parser: out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	    }
 	    return(ret);
 	}
     }
@@ -4581,6 +4591,15 @@
 	    return(NULL);
 	}
         cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
+	if (cur == NULL) {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		"xmlParseElementChildrenContentDecl : out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+	    xmlFree(elem);
+	    return(NULL);
+	}
 	GROW;
 	if (RAW == '?') {
 	    cur->ocur = XML_ELEMENT_CONTENT_OPT;
@@ -6731,18 +6750,35 @@
 		    xmlGenericError(xmlGenericErrorContext,
 			    "malloc of %ld byte failed\n",
 			    maxatts * (long)sizeof(xmlChar *));
-		    return(NULL);
+		    if (attname != NULL)
+			xmlFree(attname);
+		    if (attvalue != NULL)
+			xmlFree(attvalue);
+		    ctxt->errNo = XML_ERR_NO_MEMORY;
+		    ctxt->instate = XML_PARSER_EOF;
+		    ctxt->disableSAX = 1;
+		    goto failed;
 		}
 	    } else if (nbatts + 4 > maxatts) {
+	        const xmlChar **n;
+
 	        maxatts *= 2;
-	        atts = (const xmlChar **) xmlRealloc((void *) atts,
+	        n = (const xmlChar **) xmlRealloc((void *) atts,
 						     maxatts * sizeof(xmlChar *));
-		if (atts == NULL) {
+		if (n == NULL) {
 		    xmlGenericError(xmlGenericErrorContext,
 			    "realloc of %ld byte failed\n",
 			    maxatts * (long)sizeof(xmlChar *));
-		    return(NULL);
+		    if (attname != NULL)
+			xmlFree(attname);
+		    if (attvalue != NULL)
+			xmlFree(attvalue);
+		    ctxt->errNo = XML_ERR_NO_MEMORY;
+		    ctxt->instate = XML_PARSER_EOF;
+		    ctxt->disableSAX = 1;
+		    goto failed;
 		}
+		atts = n;
 	    }
 	    atts[nbatts++] = attname;
 	    atts[nbatts++] = attvalue;
@@ -6790,7 +6826,9 @@
         ctxt->sax->startElement(ctxt->userData, name, atts);
 
     if (atts != NULL) {
-        for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
+        for (i = 0;i < nbatts;i++)
+	    if (atts[i] != NULL)
+	       xmlFree((xmlChar *) atts[i]);
 	xmlFree((void *) atts);
     }
     return(name);
@@ -8317,6 +8355,10 @@
     xmlParseGetLasts(ctxt, &lastlt, &lastgt);
 
     while (1) {
+	if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+	    return(0);
+
+        
 	/*
 	 * Pop-up of finished entities.
 	 */
@@ -9128,6 +9170,8 @@
 int
 xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
               int terminate) {
+    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+        return(ctxt->errNo);
     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
 	int base = ctxt->input->base - ctxt->input->buf->buffer->content;
@@ -9163,6 +9207,8 @@
 	}
     }
     xmlParseTryOrFinish(ctxt, terminate);
+    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+        return(ctxt->errNo);
     if (terminate) {
 	/*
 	 * Check for termination
@@ -9259,7 +9305,9 @@
 
     ctxt = xmlNewParserCtxt();
     if (ctxt == NULL) {
-	xmlFree(buf);
+	xmlGenericError(xmlGenericErrorContext,
+		"xml parser: out of memory\n");
+	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
     if (sax != NULL) {
@@ -9267,8 +9315,10 @@
 	    xmlFree(ctxt->sax);
 	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
 	if (ctxt->sax == NULL) {
-	    xmlFree(buf);
-	    xmlFree(ctxt);
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xml parser: out of memory\n");
+	    xmlFreeParserInputBuffer(buf);
+	    xmlFreeParserCtxt(ctxt);
 	    return(NULL);
 	}
 	memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
@@ -9284,7 +9334,7 @@
     inputStream = xmlNewInputStream(ctxt);
     if (inputStream == NULL) {
 	xmlFreeParserCtxt(ctxt);
-	xmlFree(buf);
+	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
 
diff --git a/parserInternals.c b/parserInternals.c
index 8b574f2..1e2777d 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -2166,15 +2166,17 @@
  * @ctxt:  an XML parser context
  *
  * Initialize a parser context
+ *
+ * Returns 0 in case of success and -1 in case of error
  */
 
-void
+int
 xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
 {
     if(ctxt==NULL) {
 	xmlGenericError(xmlGenericErrorContext,
 		"xmlInitParserCtxt: NULL context given\n");
-        return;
+        return(-1);
     }
 
     xmlDefaultSAXHandlerInit();
@@ -2183,6 +2185,7 @@
     if (ctxt->sax == NULL) {
         xmlGenericError(xmlGenericErrorContext,
 		"xmlInitParserCtxt: out of memory\n");
+	return(-1);
     }
     else
         memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
@@ -2196,7 +2199,7 @@
 	ctxt->inputNr = 0;
 	ctxt->inputMax = 0;
 	ctxt->input = NULL;
-	return;
+	return(-1);
     }
     ctxt->inputNr = 0;
     ctxt->inputMax = 5;
@@ -2224,7 +2227,7 @@
 	ctxt->inputNr = 0;
 	ctxt->inputMax = 0;
 	ctxt->input = NULL;
-	return;
+	return(-1);
     }
     ctxt->nodeNr = 0;
     ctxt->nodeMax = 10;
@@ -2244,7 +2247,7 @@
 	ctxt->nameNr = 0;
 	ctxt->nameMax = 0;
 	ctxt->name = NULL;
-	return;
+	return(-1);
     }
     ctxt->nameNr = 0;
     ctxt->nameMax = 10;
@@ -2267,7 +2270,7 @@
 	ctxt->spaceNr = 0;
 	ctxt->spaceMax = 0;
 	ctxt->space = NULL;
-	return;
+	return(-1);
     }
     ctxt->spaceNr = 1;
     ctxt->spaceMax = 10;
@@ -2305,6 +2308,7 @@
     ctxt->charset = XML_CHAR_ENCODING_UTF8;
     ctxt->catalogs = NULL;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
+    return(0);
 }
 
 /**
@@ -2370,7 +2374,10 @@
 	return(NULL);
     }
     memset(ctxt, 0, sizeof(xmlParserCtxt));
-    xmlInitParserCtxt(ctxt);
+    if (xmlInitParserCtxt(ctxt) < 0) {
+        xmlFreeParserCtxt(ctxt);
+	return(NULL);
+    }
     return(ctxt);
 }
 
diff --git a/testOOM.c b/testOOM.c
new file mode 100644
index 0000000..8e9a302
--- /dev/null
+++ b/testOOM.c
@@ -0,0 +1,183 @@
+/*
+ * testOOM.c: Test out-of-memory handling
+ *
+ * See Copyright for the status of this software.
+ *
+ * hp@redhat.com
+ */
+
+/* FIXME this test would be much better if instead of just checking
+ * for debug spew or crashes on OOM, it also validated the expected
+ * results of parsing a particular file vs. the actual results
+ */
+
+#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
+
+
+int debug = 0;
+int dump = 0;
+int noent = 0;
+int count = 0;
+int valid = 0;
+
+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");
+    exit(1);
+}
+static int elem, attrs;
+
+static int processNode(xmlTextReaderPtr reader) {
+    int type;
+
+    type = xmlTextReaderNodeType(reader);
+    if (count) {
+	if (type == 1) {
+	    elem++;
+	    attrs += xmlTextReaderAttributeCount(reader);
+	}
+    }
+
+    return TRUE;
+}
+
+/* This always returns TRUE since we don't validate the results of
+ * parsing a particular document vs. the expected results of parsing
+ * that document. The idea is that such a failure would return FALSE.
+ */
+static int
+check_load_file_memory_func (void *data)
+{
+     const char *filename = data;
+     xmlTextReaderPtr reader;
+     int ret;
+
+     if (count) {
+          elem = 0;
+          attrs = 0;
+     }
+
+     reader = xmlNewTextReaderFilename(filename);
+     
+     if (reader != NULL) {
+          if (valid) {
+               if (xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1) == -1) {
+                    xmlFreeTextReader (reader);
+                    return TRUE;
+               }
+          }
+          
+          /*
+           * Process all nodes in sequence
+           */
+          ret = xmlTextReaderRead (reader);
+          
+          while (TRUE) {
+               if (ret == -1) {
+                    xmlFreeTextReader (reader);
+                    return TRUE;
+               } else if (ret != 1)
+                    break;
+               
+               if (!processNode(reader)) {
+                    xmlFreeTextReader (reader);
+                    return FALSE;
+               }
+               
+               ret = xmlTextReaderRead(reader);
+          }
+
+          /*
+           * Done, cleanup and status
+           */
+          xmlFreeTextReader (reader);
+
+          return TRUE;
+     } else {
+          return TRUE;
+     }
+}
+
+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);
+    
+    for (i = 1; i < argc ; i++) {
+	if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
+	    debug++;
+	else if ((!strcmp(argv[i], "-dump")) || (!strcmp(argv[i], "--dump")))
+	    dump++;
+	else 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++;
+    }
+    if (noent != 0)
+      xmlSubstituteEntitiesDefault(1);
+    for (i = 1; i < argc ; i++) {
+	if (argv[i][0] != '-') {
+             if (!test_oom_handling (check_load_file_memory_func,
+                                     argv[i])) {
+                  fprintf (stderr, "Failed!\n");
+                  return (1);
+             }
+
+             xmlCleanupParser();
+
+             if (test_get_malloc_blocks_outstanding () > 0) {
+                  fprintf (stderr, "%d blocks leaked\n",
+                           test_get_malloc_blocks_outstanding ());
+		  xmlMemoryDump();
+                  return (1);
+             }
+             
+	    files ++;
+	}
+    }
+    xmlMemoryDump();
+
+    return(0);
+}
diff --git a/testOOMlib.c b/testOOMlib.c
new file mode 100644
index 0000000..be904b3
--- /dev/null
+++ b/testOOMlib.c
@@ -0,0 +1,260 @@
+/*
+ * testOOM.c: Test out-of-memory handling
+ *
+ * See Copyright for the status of this software.
+ *
+ * Copyright 2003 Red Hat, Inc.
+ * Written by: hp@redhat.com
+ */
+
+#include "testOOMlib.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <string.h>
+
+#define _TEST_INT_MAX 2147483647
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+#include <libxml/xmlmemory.h>
+
+static int fail_alloc_counter = _TEST_INT_MAX;
+static int n_failures_per_failure = 1;
+static int n_failures_this_failure = 0;
+static int n_blocks_outstanding = 0;
+
+/**
+ * Sets the number of allocations until we simulate a failed
+ * allocation. If set to 0, the next allocation to run
+ * fails; if set to 1, one succeeds then the next fails; etc.
+ * Set to _TEST_INT_MAX to not fail anything. 
+ *
+ * @param until_next_fail number of successful allocs before one fails
+ */
+static void
+set_fail_alloc_counter (int until_next_fail)
+{
+  fail_alloc_counter = until_next_fail;
+}
+
+/**
+ * Gets the number of successful allocs until we'll simulate
+ * a failed alloc.
+ *
+ * @returns current counter value
+ */
+static int
+get_fail_alloc_counter (void)
+{
+  return fail_alloc_counter;
+}
+
+/**
+ * Sets how many mallocs to fail when the fail alloc counter reaches
+ * 0.
+ *
+ * @param number to fail
+ */
+static void
+set_fail_alloc_failures (int failures_per_failure)
+{
+  n_failures_per_failure = failures_per_failure;
+}
+
+/**
+ * Called when about to alloc some memory; if
+ * it returns #TRUE, then the allocation should
+ * fail. If it returns #FALSE, then the allocation
+ * should not fail.
+ *
+ * @returns #TRUE if this alloc should fail
+ */
+static int
+decrement_fail_alloc_counter (void)
+{
+  if (fail_alloc_counter <= 0)
+    {
+      n_failures_this_failure += 1;
+      if (n_failures_this_failure >= n_failures_per_failure)
+        {
+          fail_alloc_counter = _TEST_INT_MAX;
+
+          n_failures_this_failure = 0;
+        }
+      
+      return TRUE;
+    }
+  else
+    {
+      fail_alloc_counter -= 1;
+      return FALSE;
+    }
+}
+
+/**
+ * Get the number of outstanding malloc()'d blocks.
+ *
+ * @returns number of blocks
+ */
+int
+test_get_malloc_blocks_outstanding (void)
+{
+  return n_blocks_outstanding;
+}
+
+void*
+test_malloc (size_t bytes)
+{  
+  if (decrement_fail_alloc_counter ())
+    {
+      /* FAIL the malloc */
+      return NULL;
+    }
+  
+  if (bytes == 0) /* some system mallocs handle this, some don't */
+    return NULL;
+  else
+    {
+      void *mem;
+      mem = xmlMemMalloc (bytes);
+
+      if (mem)
+        n_blocks_outstanding += 1;
+
+      return mem;
+    }
+}
+
+void*
+test_realloc (void  *memory,
+              size_t bytes)
+{
+  if (decrement_fail_alloc_counter ())
+    {
+      /* FAIL */
+      return NULL;
+    }
+  
+  if (bytes == 0) /* guarantee this is safe */
+    {
+      test_free (memory);
+      return NULL;
+    }
+  else
+    {
+      void *mem;
+      mem = xmlMemRealloc (memory, bytes);
+
+      if (memory == NULL && mem != NULL)
+        n_blocks_outstanding += 1;
+
+      return mem;
+    }
+}
+
+void
+test_free (void  *memory)
+{
+  if (memory) /* we guarantee it's safe to free (NULL) */
+    {
+      n_blocks_outstanding -= 1;
+
+      xmlMemFree (memory);
+    }
+}
+
+char*
+test_strdup (const char *str)
+{
+  int len;
+  char *copy;
+  
+  if (str == NULL)
+    return NULL;
+  
+  len = strlen (str);
+
+  copy = test_malloc (len + 1);
+  if (copy == NULL)
+    return NULL;
+
+  memcpy (copy, str, len + 1);
+  
+  return copy;
+}
+
+static int
+run_failing_each_malloc (int                n_mallocs,
+                         TestMemoryFunction func,
+                         void              *data)
+{
+  n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
+  
+  while (n_mallocs >= 0)
+    {      
+      set_fail_alloc_counter (n_mallocs);
+
+      if (!(* func) (data))
+        return FALSE;
+      
+      n_mallocs -= 1;
+    }
+
+  set_fail_alloc_counter (_TEST_INT_MAX);
+
+  return TRUE;
+}
+
+/**
+ * Tests how well the given function responds to out-of-memory
+ * situations. Calls the function repeatedly, failing a different
+ * call to malloc() each time. If the function ever returns #FALSE,
+ * the test fails. The function should return #TRUE whenever something
+ * valid (such as returning an error, or succeeding) occurs, and #FALSE
+ * if it gets confused in some way.
+ *
+ * @param func function to call
+ * @param data data to pass to function
+ * @returns #TRUE if the function never returns FALSE
+ */
+int
+test_oom_handling (TestMemoryFunction  func,
+                   void               *data)
+{
+  int approx_mallocs;
+
+  /* Run once to see about how many mallocs are involved */
+  
+  set_fail_alloc_counter (_TEST_INT_MAX);
+
+  if (!(* func) (data))
+    return FALSE;
+
+  approx_mallocs = _TEST_INT_MAX - get_fail_alloc_counter ();
+
+  set_fail_alloc_failures (1);
+  if (!run_failing_each_malloc (approx_mallocs, func, data))
+    return FALSE;
+  
+  set_fail_alloc_failures (2);
+  if (!run_failing_each_malloc (approx_mallocs, func, data))
+    return FALSE;
+
+  set_fail_alloc_failures (3);
+  if (!run_failing_each_malloc (approx_mallocs, func, data))
+    return FALSE;
+
+  set_fail_alloc_counter (_TEST_INT_MAX);
+  
+  return TRUE;
+}
diff --git a/testOOMlib.h b/testOOMlib.h
new file mode 100644
index 0000000..751999d
--- /dev/null
+++ b/testOOMlib.h
@@ -0,0 +1,26 @@
+#ifndef TEST_OOM_LIB_H
+#define TEST_OOM_LIB_H
+
+#include <config.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+void* test_malloc  (size_t      bytes);
+void* test_realloc (void       *memory,
+                    size_t      bytes);
+void  test_free    (void       *memory);
+char* test_strdup  (const char *str);
+
+/* returns true on success */
+typedef int (* TestMemoryFunction)  (void *data);
+
+/* returns true on success */
+int test_oom_handling (TestMemoryFunction  func,
+                       void               *data);
+
+/* get number of blocks leaked */
+int test_get_malloc_blocks_outstanding (void);
+
+#endif
diff --git a/tree.c b/tree.c
index 867f074..b2445f0 100644
--- a/tree.c
+++ b/tree.c
@@ -193,6 +193,7 @@
     xmlChar *ret = NULL;
 
     *prefix = NULL;
+    if (name == NULL) return(NULL);
 
 #ifndef XML_XML_NAMESPACE
     /* xml: prefix is not really a namespace */
@@ -216,7 +217,21 @@
 	return(NULL);
 
     *prefix = xmlStrndup(name, len);
+    if (*prefix == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"xmlSplitQName2 : out of memory!\n");
+	return(NULL);
+    }
     ret = xmlStrdup(&name[len + 1]);
+    if (ret == NULL) {
+	xmlGenericError(xmlGenericErrorContext,
+		"xmlSplitQName2 : out of memory!\n");
+	if (*prefix != NULL) {
+	    xmlFree(*prefix);
+	    *prefix = NULL;
+	}
+	return(NULL);
+    }
 
     return(ret);
 }
@@ -1670,6 +1685,7 @@
     if (cur == NULL) {
         xmlGenericError(xmlGenericErrorContext,
 		"xmlNewNsPropEatName : malloc failed\n");
+        xmlFree(name);
 	return(NULL);
     }
     memset(cur, 0, sizeof(xmlAttr));
@@ -1988,6 +2004,7 @@
     if (cur == NULL) {
         xmlGenericError(xmlGenericErrorContext,
 		"xmlNewNode : malloc failed\n");
+        xmlFree(name);
 	return(NULL);
     }
     memset(cur, 0, sizeof(xmlNode));
@@ -6047,11 +6064,13 @@
  * @len:  @content length
  * 
  * Concat the given string at the end of the existing node content
+ *
+ * Returns -1 in case of error, 0 otherwise
  */
 
-void
+int
 xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
-    if (node == NULL) return;
+    if (node == NULL) return(-1);
 
     if ((node->type != XML_TEXT_NODE) &&
         (node->type != XML_CDATA_SECTION_NODE)) {
@@ -6059,9 +6078,12 @@
 	xmlGenericError(xmlGenericErrorContext,
 		"xmlTextConcat: node is not text nor CDATA\n");
 #endif
-        return;
+        return(-1);
     }
     node->content = xmlStrncat(node->content, content, len);
+    if (node->content == NULL)
+        return(-1);
+    return(0);
 }
 
 /************************************************************************
diff --git a/uri.c b/uri.c
index b5d9360..6b0aa27 100644
--- a/uri.c
+++ b/uri.c
@@ -1992,6 +1992,9 @@
     }
 
     uri = xmlCreateURI();
+    if (uri == NULL) {
+        return(NULL);
+    }
 
 #if defined(_WIN32) && !defined(__CYGWIN__)    
     len = xmlStrlen(path);
diff --git a/valid.c b/valid.c
index 2b5e051..77e7b87 100644
--- a/valid.c
+++ b/valid.c
@@ -59,24 +59,27 @@
 
 static int
 vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
-    if (ctxt->vstateMax == 0) {
+    if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
 	ctxt->vstateMax = 10;
 	ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
 		              sizeof(ctxt->vstateTab[0]));
         if (ctxt->vstateTab == NULL) {
-	    VERROR(ctxt->userData, "realloc failed !n");
+	    VERROR(ctxt->userData, "malloc failed !n");
 	    return(-1);
 	}
     }
 
     if (ctxt->vstateNr >= ctxt->vstateMax) {
-	ctxt->vstateMax *= 2;
-        ctxt->vstateTab = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
-	             ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
-        if (ctxt->vstateTab == NULL) {
+        xmlValidState *tmp;
+
+	tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
+	             2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
+        if (tmp == NULL) {
 	    VERROR(ctxt->userData, "realloc failed !n");
 	    return(-1);
 	}
+	ctxt->vstateMax *= 2;
+	ctxt->vstateTab = tmp;
     }
     ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
     ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
@@ -161,15 +164,28 @@
     if (ctxt->vstateNr > MAX_RECURSE) {
 	return(-1);
     }
+    if (ctxt->vstateTab == NULL) {
+	ctxt->vstateMax = 8;
+	ctxt->vstateTab = (xmlValidState *) xmlMalloc(
+		     ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
+	if (ctxt->vstateTab == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "malloc failed !n");
+	    return(-1);
+	}
+    }
     if (ctxt->vstateNr >= ctxt->vstateMax) {
-	ctxt->vstateMax *= 2;
-        ctxt->vstateTab = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
-	             ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
-        if (ctxt->vstateTab == NULL) {
+        xmlValidState *tmp;
+
+        tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
+	             2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
+        if (tmp == NULL) {
 	    xmlGenericError(xmlGenericErrorContext,
 		    "realloc failed !n");
 	    return(-1);
 	}
+	ctxt->vstateMax *= 2;
+	ctxt->vstateTab = tmp;
 	ctxt->vstate = &ctxt->vstateTab[0];
     }
     /*
@@ -219,15 +235,15 @@
         }
     }
     if (ctxt->nodeNr >= ctxt->nodeMax) {
-        ctxt->nodeMax *= 2;
-        ctxt->nodeTab =
-            (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
-                                      ctxt->nodeMax *
-                                      sizeof(ctxt->nodeTab[0]));
-        if (ctxt->nodeTab == NULL) {
+        xmlNodePtr *tmp;
+        tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
+			      ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
+        if (tmp == NULL) {
             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
             return (0);
         }
+        ctxt->nodeMax *= 2;
+	ctxt->nodeTab = tmp;
     }
     ctxt->nodeTab[ctxt->nodeNr] = value;
     ctxt->node = value;
@@ -635,7 +651,7 @@
     xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
     elem->contModel = xmlAutomataCompile(ctxt->am);
-    if (!xmlRegexpIsDeterminist(elem->contModel)) {
+    if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
 	char expr[5000];
 	expr[0] = 0;
 	xmlSnprintfElementContent(expr, 5000, elem->content, 1);
@@ -901,7 +917,8 @@
 		strcat(buf, " ...");
 		return;
 	    }
-	    strcat(buf, (char *) content->name);
+	    if (content->name != NULL)
+		strcat(buf, (char *) content->name);
 	    break;
 	case XML_ELEMENT_CONTENT_SEQ:
 	    if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
@@ -1086,6 +1103,10 @@
     if (table == NULL) {
 	xmlGenericError(xmlGenericErrorContext,
 		"xmlAddElementDecl: Table creation failed!\n");
+	if (uqname != NULL)
+	    xmlFree(uqname);
+	if (ns != NULL)
+	    xmlFree(ns);
         return(NULL);
     }
 
@@ -1116,6 +1137,8 @@
 	    VERROR(ctxt->userData, "Redefinition of element %s\n", name);
 	    if (uqname != NULL)
 		xmlFree(uqname);
+            if (ns != NULL)
+	        xmlFree(ns);
 	    return(NULL);
 	}
     } else {
@@ -1123,6 +1146,10 @@
 	if (ret == NULL) {
 	    xmlGenericError(xmlGenericErrorContext,
 		    "xmlAddElementDecl: out of memory\n");
+	    if (uqname != NULL)
+		xmlFree(uqname);
+            if (ns != NULL)
+	        xmlFree(ns);
 	    return(NULL);
 	}
 	memset(ret, 0, sizeof(xmlElement));
@@ -1132,6 +1159,16 @@
 	 * fill the structure.
 	 */
 	ret->name = xmlStrdup(name);
+	if (ret->name == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		    "xmlAddElementDecl: out of memory\n");
+	    if (uqname != NULL)
+		xmlFree(uqname);
+            if (ns != NULL)
+	        xmlFree(ns);
+	    xmlFree(ret);
+	    return(NULL);
+	}
 	ret->prefix = ns;
 
 	/*
@@ -2667,7 +2704,7 @@
     xmlElementPtr cur;
     xmlChar *uqname = NULL, *prefix = NULL;
 
-    if (dtd == NULL) return(NULL);
+    if ((dtd == NULL) || (name == NULL)) return(NULL);
     if (dtd->elements == NULL)
 	return(NULL);
     table = (xmlElementTablePtr) dtd->elements;
@@ -4641,7 +4678,7 @@
     if (elemDecl->contModel == NULL)
 	ret = xmlValidBuildContentModel(ctxt, elemDecl);
     if (elemDecl->contModel == NULL) {
-	ret = -1;
+	return(-1);
     } else {
 	xmlRegExecCtxtPtr exec;
 
@@ -4837,14 +4874,14 @@
 	    char list[5000];
 
 	    expr[0] = 0;
-	    xmlSnprintfElementContent(expr, 5000, cont, 1);
+	    xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
 	    list[0] = 0;
 #ifndef LIBXML_REGEXP_ENABLED
 	    if (repl != NULL)
-		xmlSnprintfElements(list, 5000, repl, 1);
+		xmlSnprintfElements(&list[0], 5000, repl, 1);
 	    else
 #endif /* LIBXML_REGEXP_ENABLED */
-		xmlSnprintfElements(list, 5000, child, 1);
+		xmlSnprintfElements(&list[0], 5000, child, 1);
 
 	    if (name != NULL) {
 		if (parent != NULL) VECTXT(ctxt, parent);
diff --git a/xmlmemory.c b/xmlmemory.c
index c8aa793..38cb659 100644
--- a/xmlmemory.c
+++ b/xmlmemory.c
@@ -305,6 +305,8 @@
     unsigned long number;
 
     if (!xmlMemInitialized) xmlInitMemory();
+    if (ptr == NULL)
+        return(NULL);
     TEST_POINT
 
     p = CLIENT_2_HDR(ptr);
diff --git a/xmlreader.c b/xmlreader.c
index 9a24110..c7b4015 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -83,7 +83,8 @@
     XML_TEXTREADER_END= 2,
     XML_TEXTREADER_EMPTY= 3,
     XML_TEXTREADER_BACKTRACK= 4,
-    XML_TEXTREADER_DONE= 5
+    XML_TEXTREADER_DONE= 5,
+    XML_TEXTREADER_ERROR= 6
 } xmlTextReaderState;
 
 typedef enum {
@@ -417,6 +418,7 @@
 		    s, 1);
 	    reader->cur = inbuf->use;
 	    reader->mode = XML_TEXTREADER_DONE;
+	    if (val != 0) return(-1);
 	}
     }
     reader->state = oldstate;
@@ -1151,11 +1153,17 @@
 	ret->base = 0;
 	ret->cur = 0;
     }
+    if (ret->ctxt == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+		"xmlNewTextReader : malloc failed\n");
+	xmlFree(ret->sax);
+	xmlFree(ret);
+	return(NULL);
+    }
     ret->ctxt->_private = ret;
     ret->ctxt->linenumbers = 1;
     ret->allocs = XML_TEXTREADER_CTXT;
     return(ret);
-
 }
 
 /**
diff --git a/xmlregexp.c b/xmlregexp.c
index 8f1e9c1..6ea1bfe 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -332,23 +332,19 @@
     xmlRegexpPtr ret;
 
     ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
-    if (ret == NULL)
+    if (ret == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+	     "out of memory compiling regexp\n");
 	return(NULL);
+    }
     memset(ret, 0, sizeof(xmlRegexp));
     ret->string = ctxt->string;
-    ctxt->string = NULL;
     ret->nbStates = ctxt->nbStates;
-    ctxt->nbStates = 0;
     ret->states = ctxt->states;
-    ctxt->states = NULL;
     ret->nbAtoms = ctxt->nbAtoms;
-    ctxt->nbAtoms = 0;
     ret->atoms = ctxt->atoms;
-    ctxt->atoms = NULL;
     ret->nbCounters = ctxt->nbCounters;
-    ctxt->nbCounters = 0;
     ret->counters = ctxt->counters;
-    ctxt->counters = NULL;
     ret->determinist = ctxt->determinist;
 
     if ((ret->determinist != 0) &&
@@ -373,6 +369,12 @@
 	 */
 
 	stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
+	if (stateRemap == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		 "out of memory compiling regexp\n");
+	    xmlFree(ret);
+	    return(NULL);
+	}
 	for (i = 0;i < ret->nbStates;i++) {
 	    if (ret->states[i] != NULL) {
 		stateRemap[i] = nbstates;
@@ -385,7 +387,22 @@
 	printf("Final: %d states\n", nbstates);
 #endif
 	stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
+	if (stringMap == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		 "out of memory compiling regexp\n");
+	    xmlFree(stateRemap);
+	    xmlFree(ret);
+	    return(NULL);
+	}
 	stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int));
+	if (stringRemap == NULL) {
+	    xmlGenericError(xmlGenericErrorContext,
+		 "out of memory compiling regexp\n");
+	    xmlFree(stringMap);
+	    xmlFree(stateRemap);
+	    xmlFree(ret);
+	    return(NULL);
+	}
 	for (i = 0;i < ret->nbAtoms;i++) {
 	    if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
 		(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
@@ -399,6 +416,15 @@
 		if (j >= nbatoms) {
 		    stringRemap[i] = nbatoms;
 		    stringMap[nbatoms] = xmlStrdup(value);
+		    if (stringMap[nbatoms] == NULL) {
+			for (i = 0;i < nbatoms;i++)
+			    xmlFree(stringMap[i]);
+			xmlFree(stringRemap);
+			xmlFree(stringMap);
+			xmlFree(stateRemap);
+			xmlFree(ret);
+			return(NULL);
+		    }
 		    nbatoms++;
 		}
 	    } else {
@@ -407,20 +433,29 @@
 		for (i = 0;i < nbatoms;i++)
 		    xmlFree(stringMap[i]);
 		xmlFree(stringMap);
-		goto fail_compact;
+		xmlFree(ret);
+		return(NULL);
 	    }
 	}
 #ifdef DEBUG_COMPACTION
 	printf("Final: %d atoms\n", nbatoms);
 #endif
+	transitions = (int *) xmlMalloc((nbstates + 1) *
+	                                (nbatoms + 1) * sizeof(int));
+	if (transitions == NULL) {
+	    xmlFree(stateRemap);
+	    xmlFree(stringRemap);
+	    xmlFree(stringMap);
+	    xmlFree(ret);
+	    return(NULL);
+	}
+	memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int));
 
 	/*
 	 * Allocate the transition table. The first entry for each
 	 * state correspond to the state type.
 	 */
-	transitions = (int *) xmlMalloc(nbstates * (nbatoms + 1) * sizeof(int));
 	transdata = NULL;
-	memset(transitions, 0, nbstates * (nbatoms + 1) * sizeof(int));
 
 	for (i = 0;i < ret->nbStates;i++) {
 	    int stateno, atomno, targetno, prev;
@@ -445,6 +480,11 @@
 		    if (transdata != NULL)
 			memset(transdata, 0,
 			       nbstates * nbatoms * sizeof(void *));
+		    else {
+			xmlGenericError(xmlGenericErrorContext,
+			     "out of memory compiling regexp\n");
+			break;
+		    }
 		}
 		targetno = stateRemap[trans->to];
 		/*
@@ -470,7 +510,7 @@
 			for (i = 0;i < nbatoms;i++)
 			    xmlFree(stringMap[i]);
 			xmlFree(stringMap);
-			goto fail_compact;
+			goto not_determ;
 		    }
 		} else {
 #if 0
@@ -524,7 +564,14 @@
 	xmlFree(stateRemap);
 	xmlFree(stringRemap);
     }
-fail_compact:
+not_determ:
+    ctxt->string = NULL;
+    ctxt->nbStates = 0;
+    ctxt->states = NULL;
+    ctxt->nbAtoms = 0;
+    ctxt->atoms = NULL;
+    ctxt->nbCounters = 0;
+    ctxt->counters = NULL;
     return(ret);
 }
 
@@ -1048,11 +1095,11 @@
     return(ctxt->nbCounters++);
 }
 
-static void 
+static int 
 xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
     if (atom == NULL) {
 	ERROR("atom push: atom is NULL");
-	return;
+	return(-1);
     }
     if (ctxt->maxAtoms == 0) {
 	ctxt->maxAtoms = 4;
@@ -1061,7 +1108,7 @@
 	if (ctxt->atoms == NULL) {
 	    ERROR("atom push: allocation failed");
 	    ctxt->maxAtoms = 0;
-	    return;
+	    return(-1);
 	}
     } else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
 	xmlRegAtomPtr *tmp;
@@ -1071,12 +1118,13 @@
 	if (tmp == NULL) {
 	    ERROR("atom push: allocation failed");
 	    ctxt->maxAtoms /= 2;
-	    return;
+	    return(-1);
 	}
 	ctxt->atoms = tmp;
     }
     atom->no = ctxt->nbAtoms;
     ctxt->atoms[ctxt->nbAtoms++] = atom;
+    return(0);
 }
 
 static void 
@@ -1132,8 +1180,9 @@
     state->nbTrans++;
 }
 
-static void 
+static int
 xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
+    if (state == NULL) return(-1);
     if (ctxt->maxStates == 0) {
 	ctxt->maxStates = 4;
 	ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
@@ -1141,7 +1190,7 @@
 	if (ctxt->states == NULL) {
 	    ERROR("add range: allocation failed");
 	    ctxt->maxStates = 0;
-	    return;
+	    return(-1);
 	}
     } else if (ctxt->nbStates >= ctxt->maxStates) {
 	xmlRegStatePtr *tmp;
@@ -1151,12 +1200,13 @@
 	if (tmp == NULL) {
 	    ERROR("add range: allocation failed");
 	    ctxt->maxStates /= 2;
-	    return;
+	    return(-1);
 	}
 	ctxt->states = tmp;
     }
     state->no = ctxt->nbStates;
     ctxt->states[ctxt->nbStates++] = state;
+    return(0);
 }
 
 /**
@@ -1245,20 +1295,23 @@
  * @to:  the target state or NULL for building a new one
  * @atom:  the atom generating the transition
  *
+ * Returns 0 if succes and -1 in case of error.
  */
-static void
+static int
 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
 	                 xmlRegStatePtr to, xmlRegAtomPtr atom) {
     if (atom == NULL) {
 	ERROR("genrate transition: atom == NULL");
-	return;
+	return(-1);
     }
     if (atom->type == XML_REGEXP_SUBREG) {
 	/*
 	 * this is a subexpression handling one should not need to
 	 * create a new node excep for XML_REGEXP_QUANT_RANGE.
 	 */
-	xmlRegAtomPush(ctxt, atom);
+	if (xmlRegAtomPush(ctxt, atom) < 0) {
+	    return(-1);
+	}
 	if ((to != NULL) && (atom->stop != to) &&
 	    (atom->quant != XML_REGEXP_QUANT_RANGE)) {
 	    /*
@@ -1314,14 +1367,20 @@
 	    default:
 		break;
 	}
-	return;
+	return(0);
     } else {
 	if (to == NULL) {
 	    to = xmlRegNewState(ctxt);
-	    xmlRegStatePush(ctxt, to);
+	    if (to != NULL)
+		xmlRegStatePush(ctxt, to);
+	    else {
+		return(-1);
+	    }
+	}
+	if (xmlRegAtomPush(ctxt, atom) < 0) {
+	    return(-1);
 	}
 	xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
-	xmlRegAtomPush(ctxt, atom);
 	ctxt->state = to;
     }
     switch (atom->quant) {
@@ -1341,6 +1400,7 @@
 	default:
 	    break;
     }
+    return(0);
 }
 
 /**
@@ -1433,6 +1493,9 @@
     int statenr, transnr;
     xmlRegStatePtr state;
 
+    if (ctxt->states == NULL) return;
+
+
     /*
      * build the completed transitions bypassing the epsilons
      * Use a marking algorithm to avoid loops
@@ -2276,6 +2339,8 @@
 
     if (comp == NULL)
 	return(NULL);
+    if ((comp->compact == NULL) && (comp->states == NULL))
+        return(NULL);
     exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
     if (exec == NULL) {
 	return(NULL);
@@ -3568,6 +3633,8 @@
  * @ctxt:  a regexp parser context
  *
  * [8]   QuantExact   ::=   [0-9]+
+ *
+ * Returns 0 if success or -1 in case of error
  */
 static int
 xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
@@ -3723,8 +3790,9 @@
  * @first:  is taht the first
  *
  * [2]   branch   ::=   piece*
+ 8
  */
-static void
+static int
 xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
     xmlRegStatePtr previous;
     xmlRegAtomPtr prevatom = NULL;
@@ -3734,7 +3802,8 @@
     ret = xmlFAParsePiece(ctxt);
     if (ret != 0) {
 	if (first) {
-	    xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
+	    if (xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom) < 0)
+	        return(-1);
 	    previous = ctxt->state;
 	} else {
 	    prevatom = ctxt->atom;
@@ -3745,9 +3814,13 @@
 	ret = xmlFAParsePiece(ctxt);
 	if (ret != 0) {
 	    if (first) {
-		xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
+		if (xmlFAGenerateTransitions(ctxt, previous, NULL,
+		                             ctxt->atom) < 0)
+		    return(-1);
 	    } else {
-		xmlFAGenerateTransitions(ctxt, previous, NULL, prevatom);
+		if (xmlFAGenerateTransitions(ctxt, previous, NULL,
+		                             prevatom) < 0)
+		    return(-1);
 		prevatom = ctxt->atom;
 	    }
 	    previous = ctxt->state;
@@ -3755,8 +3828,10 @@
 	}
     }
     if (!first) {
-	xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom);
+	if (xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom) < 0)
+	    return(-1);
     }
+    return(0);
 }
 
 /**
@@ -3994,7 +4069,15 @@
     /* initialize the parser */
     ctxt->end = NULL;
     ctxt->start = ctxt->state = xmlRegNewState(ctxt);
-    xmlRegStatePush(ctxt, ctxt->start);
+    if (ctxt->start == NULL) {
+	xmlFreeAutomata(ctxt);
+	return(NULL);
+    }
+    if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
+        xmlRegFreeState(ctxt->start);
+	xmlFreeAutomata(ctxt);
+	return(NULL);
+    }
 
     return(ctxt);
 }
@@ -4067,12 +4150,17 @@
     if ((am == NULL) || (from == NULL) || (token == NULL))
 	return(NULL);
     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
+    if (atom == NULL)
+        return(NULL);
     atom->data = data;
     if (atom == NULL)
 	return(NULL);
     atom->valuep = xmlStrdup(token);
 
-    xmlFAGenerateTransitions(am, from, to, atom);
+    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+        xmlRegFreeAtom(atom);
+	return(NULL);
+    }
     if (to == NULL)
 	return(am->state);
     return(to);
@@ -4127,7 +4215,10 @@
 	atom->valuep = str;
     }
 
-    xmlFAGenerateTransitions(am, from, to, atom);
+    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+        xmlRegFreeAtom(atom);
+	return(NULL);
+    }
     if (to == NULL)
 	return(am->state);
     return(to);
@@ -4173,7 +4264,10 @@
 	atom->min = min;
     atom->max = max;
 
-    xmlFAGenerateTransitions(am, from, to, atom);
+    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+        xmlRegFreeAtom(atom);
+	return(NULL);
+    }
     if (to == NULL)
 	to = am->state;
     if (to == NULL)
@@ -4400,6 +4494,7 @@
 xmlAutomataCompile(xmlAutomataPtr am) {
     xmlRegexpPtr ret;
 
+    if ((am == NULL) || (am->error != 0)) return(NULL);
     xmlFAEliminateEpsilonTransitions(am);
     /* xmlFAComputesDeterminism(am); */
     ret = xmlRegEpxFromParse(am);