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/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);