mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-22 04:01:59 +03:00
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
This commit is contained in:
11
ChangeLog
11
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>
|
Wed Apr 23 17:16:41 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* xmlschemastypes.c: trivial fix for 109774 removing a warning
|
* xmlschemastypes.c: trivial fix for 109774 removing a warning
|
||||||
|
@ -116,6 +116,11 @@ testReader_LDFLAGS =
|
|||||||
testReader_DEPENDENCIES = $(DEPS)
|
testReader_DEPENDENCIES = $(DEPS)
|
||||||
testReader_LDADD= $(LDADDS)
|
testReader_LDADD= $(LDADDS)
|
||||||
|
|
||||||
|
testOOM_SOURCES=testOOM.c testOOMlib.h testOOMlib.c
|
||||||
|
testOOM_LDFLAGS =
|
||||||
|
testOOM_DEPENDENCIES = $(DEPS)
|
||||||
|
testOOM_LDADD= $(LDADDS)
|
||||||
|
|
||||||
check-local: tests
|
check-local: tests
|
||||||
|
|
||||||
testall : tests SVGtests SAXtests
|
testall : tests SVGtests SAXtests
|
||||||
|
106
SAX.c
106
SAX.c
@ -232,6 +232,8 @@ externalSubset(void *ctx, const xmlChar *name,
|
|||||||
ctxt->sax->error(ctxt->userData,
|
ctxt->sax->error(ctxt->userData,
|
||||||
"externalSubset: out of memory\n");
|
"externalSubset: out of memory\n");
|
||||||
ctxt->errNo = XML_ERR_NO_MEMORY;
|
ctxt->errNo = XML_ERR_NO_MEMORY;
|
||||||
|
ctxt->instate = XML_PARSER_EOF;
|
||||||
|
ctxt->disableSAX = 1;
|
||||||
ctxt->input = oldinput;
|
ctxt->input = oldinput;
|
||||||
ctxt->inputNr = oldinputNr;
|
ctxt->inputNr = oldinputNr;
|
||||||
ctxt->inputMax = oldinputMax;
|
ctxt->inputMax = oldinputMax;
|
||||||
@ -745,12 +747,25 @@ startDocument(void *ctx)
|
|||||||
"SAX.startDocument()\n");
|
"SAX.startDocument()\n");
|
||||||
#endif
|
#endif
|
||||||
if (ctxt->html) {
|
if (ctxt->html) {
|
||||||
if (ctxt->myDoc == NULL)
|
|
||||||
#ifdef LIBXML_HTML_ENABLED
|
#ifdef LIBXML_HTML_ENABLED
|
||||||
|
if (ctxt->myDoc == NULL)
|
||||||
ctxt->myDoc = htmlNewDocNoDtD(NULL, 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
|
#else
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"libxml2 built without HTML support\n");
|
"libxml2 built without HTML support\n");
|
||||||
|
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
|
||||||
|
ctxt->instate = XML_PARSER_EOF;
|
||||||
|
ctxt->disableSAX = 1;
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
|
doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
|
||||||
@ -760,6 +775,14 @@ startDocument(void *ctx)
|
|||||||
else
|
else
|
||||||
doc->encoding = NULL;
|
doc->encoding = NULL;
|
||||||
doc->standalone = ctxt->standalone;
|
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) &&
|
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
|
||||||
@ -839,6 +862,17 @@ my_attribute(void *ctx, const xmlChar *fullname, const xmlChar *value,
|
|||||||
* Split the full name into a namespace prefix and the tag name
|
* Split the full name into a namespace prefix and the tag name
|
||||||
*/
|
*/
|
||||||
name = xmlSplitQName(ctxt, fullname, &ns);
|
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
|
* Do the last stage of the attribute normalization
|
||||||
@ -921,6 +955,18 @@ my_attribute(void *ctx, const xmlChar *fullname, const xmlChar *value,
|
|||||||
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
|
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
|
||||||
0,0,0);
|
0,0,0);
|
||||||
ctxt->depth--;
|
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 {
|
} else {
|
||||||
val = (xmlChar *) value;
|
val = (xmlChar *) value;
|
||||||
}
|
}
|
||||||
@ -1200,14 +1246,19 @@ process_external_subset:
|
|||||||
attr->elem, attr->name,
|
attr->elem, attr->name,
|
||||||
attr->prefix);
|
attr->prefix);
|
||||||
if ((tst == attr) || (tst == NULL)) {
|
if ((tst == attr) || (tst == NULL)) {
|
||||||
|
xmlChar fn[50];
|
||||||
xmlChar *fulln;
|
xmlChar *fulln;
|
||||||
|
|
||||||
if (attr->prefix != NULL) {
|
fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
|
||||||
fulln = xmlStrdup(attr->prefix);
|
if (fulln == NULL) {
|
||||||
fulln = xmlStrcat(fulln, BAD_CAST ":");
|
if ((ctxt->sax != NULL) &&
|
||||||
fulln = xmlStrcat(fulln, attr->name);
|
(ctxt->sax->error != NULL))
|
||||||
} else {
|
ctxt->sax->error(ctxt->userData,
|
||||||
fulln = xmlStrdup(attr->name);
|
"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 @@ process_external_subset:
|
|||||||
my_attribute(ctxt, fulln, attr->defaultValue,
|
my_attribute(ctxt, fulln, attr->defaultValue,
|
||||||
prefix);
|
prefix);
|
||||||
}
|
}
|
||||||
xmlFree(fulln);
|
if ((fulln != fn) && (fulln != attr->name))
|
||||||
|
xmlFree(fulln);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1301,7 +1353,14 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
|||||||
* an attribute at this level.
|
* an attribute at this level.
|
||||||
*/
|
*/
|
||||||
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
|
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) {
|
if (ctxt->myDoc->children == NULL) {
|
||||||
#ifdef DEBUG_SAX_TREE
|
#ifdef DEBUG_SAX_TREE
|
||||||
xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
|
xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
|
||||||
@ -1587,6 +1646,9 @@ characters(void *ctx, const xmlChar *ch, int len)
|
|||||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
||||||
ctxt->sax->error(ctxt->userData,
|
ctxt->sax->error(ctxt->userData,
|
||||||
"SAX.characters(): out of memory\n");
|
"SAX.characters(): out of memory\n");
|
||||||
|
ctxt->errNo = XML_ERR_NO_MEMORY;
|
||||||
|
ctxt->instate = XML_PARSER_EOF;
|
||||||
|
ctxt->disableSAX = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctxt->nodemem = size;
|
ctxt->nodemem = size;
|
||||||
@ -1596,7 +1658,14 @@ characters(void *ctx, const xmlChar *ch, int len)
|
|||||||
ctxt->nodelen += len;
|
ctxt->nodelen += len;
|
||||||
lastChild->content[ctxt->nodelen] = 0;
|
lastChild->content[ctxt->nodelen] = 0;
|
||||||
} else if (coalesceText) {
|
} 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) {
|
if (ctxt->node->children != NULL) {
|
||||||
ctxt->nodelen = xmlStrlen(lastChild->content);
|
ctxt->nodelen = xmlStrlen(lastChild->content);
|
||||||
ctxt->nodemem = ctxt->nodelen + 1;
|
ctxt->nodemem = ctxt->nodelen + 1;
|
||||||
@ -1604,10 +1673,19 @@ characters(void *ctx, const xmlChar *ch, int len)
|
|||||||
} else {
|
} else {
|
||||||
/* Mixed content, first time */
|
/* Mixed content, first time */
|
||||||
lastChild = xmlNewTextLen(ch, len);
|
lastChild = xmlNewTextLen(ch, len);
|
||||||
xmlAddChild(ctxt->node, lastChild);
|
if (lastChild == NULL) {
|
||||||
if (ctxt->node->children != NULL) {
|
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
|
||||||
ctxt->nodelen = len;
|
ctxt->sax->error(ctxt->userData,
|
||||||
ctxt->nodemem = len + 1;
|
"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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
407
check-relaxng-test-suite2.py
Executable file
407
check-relaxng-test-suite2.py
Executable file
@ -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()
|
@ -802,7 +802,7 @@ int xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx,
|
|||||||
/*
|
/*
|
||||||
* Parser contexts handling.
|
* Parser contexts handling.
|
||||||
*/
|
*/
|
||||||
void xmlInitParserCtxt (xmlParserCtxtPtr ctxt);
|
int xmlInitParserCtxt (xmlParserCtxtPtr ctxt);
|
||||||
void xmlClearParserCtxt (xmlParserCtxtPtr ctxt);
|
void xmlClearParserCtxt (xmlParserCtxtPtr ctxt);
|
||||||
void xmlFreeParserCtxt (xmlParserCtxtPtr ctxt);
|
void xmlFreeParserCtxt (xmlParserCtxtPtr ctxt);
|
||||||
void xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt,
|
void xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt,
|
||||||
|
@ -724,7 +724,7 @@ xmlNodePtr xmlAddNextSibling (xmlNodePtr cur,
|
|||||||
void xmlUnlinkNode (xmlNodePtr cur);
|
void xmlUnlinkNode (xmlNodePtr cur);
|
||||||
xmlNodePtr xmlTextMerge (xmlNodePtr first,
|
xmlNodePtr xmlTextMerge (xmlNodePtr first,
|
||||||
xmlNodePtr second);
|
xmlNodePtr second);
|
||||||
void xmlTextConcat (xmlNodePtr node,
|
int xmlTextConcat (xmlNodePtr node,
|
||||||
const xmlChar *content,
|
const xmlChar *content,
|
||||||
int len);
|
int len);
|
||||||
void xmlFreeNodeList (xmlNodePtr cur);
|
void xmlFreeNodeList (xmlNodePtr cur);
|
||||||
|
68
parser.c
68
parser.c
@ -1720,6 +1720,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
|
|||||||
|
|
||||||
*prefix = NULL;
|
*prefix = NULL;
|
||||||
|
|
||||||
|
if (cur == NULL) return(NULL);
|
||||||
|
|
||||||
#ifndef XML_XML_NAMESPACE
|
#ifndef XML_XML_NAMESPACE
|
||||||
/* xml: prefix is not really a namespace */
|
/* xml: prefix is not really a namespace */
|
||||||
if ((cur[0] == 'x') && (cur[1] == 'm') &&
|
if ((cur[0] == 'x') && (cur[1] == 'm') &&
|
||||||
@ -1905,6 +1907,14 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
|
|||||||
ctxt->input->cur = in;
|
ctxt->input->cur = in;
|
||||||
ctxt->nbChars += count;
|
ctxt->nbChars += count;
|
||||||
ctxt->input->col += 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);
|
return(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4581,6 +4591,15 @@ xmlParseElementChildrenContentDecl
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
|
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;
|
GROW;
|
||||||
if (RAW == '?') {
|
if (RAW == '?') {
|
||||||
cur->ocur = XML_ELEMENT_CONTENT_OPT;
|
cur->ocur = XML_ELEMENT_CONTENT_OPT;
|
||||||
@ -6731,18 +6750,35 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
|
|||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"malloc of %ld byte failed\n",
|
"malloc of %ld byte failed\n",
|
||||||
maxatts * (long)sizeof(xmlChar *));
|
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) {
|
} else if (nbatts + 4 > maxatts) {
|
||||||
|
const xmlChar **n;
|
||||||
|
|
||||||
maxatts *= 2;
|
maxatts *= 2;
|
||||||
atts = (const xmlChar **) xmlRealloc((void *) atts,
|
n = (const xmlChar **) xmlRealloc((void *) atts,
|
||||||
maxatts * sizeof(xmlChar *));
|
maxatts * sizeof(xmlChar *));
|
||||||
if (atts == NULL) {
|
if (n == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"realloc of %ld byte failed\n",
|
"realloc of %ld byte failed\n",
|
||||||
maxatts * (long)sizeof(xmlChar *));
|
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++] = attname;
|
||||||
atts[nbatts++] = attvalue;
|
atts[nbatts++] = attvalue;
|
||||||
@ -6790,7 +6826,9 @@ failed:
|
|||||||
ctxt->sax->startElement(ctxt->userData, name, atts);
|
ctxt->sax->startElement(ctxt->userData, name, atts);
|
||||||
|
|
||||||
if (atts != NULL) {
|
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);
|
xmlFree((void *) atts);
|
||||||
}
|
}
|
||||||
return(name);
|
return(name);
|
||||||
@ -8317,6 +8355,10 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
|
|||||||
xmlParseGetLasts(ctxt, &lastlt, &lastgt);
|
xmlParseGetLasts(ctxt, &lastlt, &lastgt);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pop-up of finished entities.
|
* Pop-up of finished entities.
|
||||||
*/
|
*/
|
||||||
@ -9128,6 +9170,8 @@ done:
|
|||||||
int
|
int
|
||||||
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
|
xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
|
||||||
int terminate) {
|
int terminate) {
|
||||||
|
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
|
||||||
|
return(ctxt->errNo);
|
||||||
if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
|
if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
|
||||||
(ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) {
|
(ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF)) {
|
||||||
int base = ctxt->input->base - ctxt->input->buf->buffer->content;
|
int base = ctxt->input->base - ctxt->input->buf->buffer->content;
|
||||||
@ -9163,6 +9207,8 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlParseTryOrFinish(ctxt, terminate);
|
xmlParseTryOrFinish(ctxt, terminate);
|
||||||
|
if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
|
||||||
|
return(ctxt->errNo);
|
||||||
if (terminate) {
|
if (terminate) {
|
||||||
/*
|
/*
|
||||||
* Check for termination
|
* Check for termination
|
||||||
@ -9259,7 +9305,9 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
|
|||||||
|
|
||||||
ctxt = xmlNewParserCtxt();
|
ctxt = xmlNewParserCtxt();
|
||||||
if (ctxt == NULL) {
|
if (ctxt == NULL) {
|
||||||
xmlFree(buf);
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xml parser: out of memory\n");
|
||||||
|
xmlFreeParserInputBuffer(buf);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
if (sax != NULL) {
|
if (sax != NULL) {
|
||||||
@ -9267,8 +9315,10 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
|
|||||||
xmlFree(ctxt->sax);
|
xmlFree(ctxt->sax);
|
||||||
ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
|
ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
|
||||||
if (ctxt->sax == NULL) {
|
if (ctxt->sax == NULL) {
|
||||||
xmlFree(buf);
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
xmlFree(ctxt);
|
"xml parser: out of memory\n");
|
||||||
|
xmlFreeParserInputBuffer(buf);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
|
memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
|
||||||
@ -9284,7 +9334,7 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
|
|||||||
inputStream = xmlNewInputStream(ctxt);
|
inputStream = xmlNewInputStream(ctxt);
|
||||||
if (inputStream == NULL) {
|
if (inputStream == NULL) {
|
||||||
xmlFreeParserCtxt(ctxt);
|
xmlFreeParserCtxt(ctxt);
|
||||||
xmlFree(buf);
|
xmlFreeParserInputBuffer(buf);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2166,15 +2166,17 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
|
|||||||
* @ctxt: an XML parser context
|
* @ctxt: an XML parser context
|
||||||
*
|
*
|
||||||
* Initialize a parser context
|
* Initialize a parser context
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
int
|
||||||
xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
||||||
{
|
{
|
||||||
if(ctxt==NULL) {
|
if(ctxt==NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlInitParserCtxt: NULL context given\n");
|
"xmlInitParserCtxt: NULL context given\n");
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlDefaultSAXHandlerInit();
|
xmlDefaultSAXHandlerInit();
|
||||||
@ -2183,6 +2185,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
if (ctxt->sax == NULL) {
|
if (ctxt->sax == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlInitParserCtxt: out of memory\n");
|
"xmlInitParserCtxt: out of memory\n");
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
|
memcpy(ctxt->sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
|
||||||
@ -2196,7 +2199,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->inputNr = 0;
|
ctxt->inputNr = 0;
|
||||||
ctxt->inputMax = 0;
|
ctxt->inputMax = 0;
|
||||||
ctxt->input = NULL;
|
ctxt->input = NULL;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->inputNr = 0;
|
ctxt->inputNr = 0;
|
||||||
ctxt->inputMax = 5;
|
ctxt->inputMax = 5;
|
||||||
@ -2224,7 +2227,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->inputNr = 0;
|
ctxt->inputNr = 0;
|
||||||
ctxt->inputMax = 0;
|
ctxt->inputMax = 0;
|
||||||
ctxt->input = NULL;
|
ctxt->input = NULL;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->nodeNr = 0;
|
ctxt->nodeNr = 0;
|
||||||
ctxt->nodeMax = 10;
|
ctxt->nodeMax = 10;
|
||||||
@ -2244,7 +2247,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->nameNr = 0;
|
ctxt->nameNr = 0;
|
||||||
ctxt->nameMax = 0;
|
ctxt->nameMax = 0;
|
||||||
ctxt->name = NULL;
|
ctxt->name = NULL;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->nameNr = 0;
|
ctxt->nameNr = 0;
|
||||||
ctxt->nameMax = 10;
|
ctxt->nameMax = 10;
|
||||||
@ -2267,7 +2270,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->spaceNr = 0;
|
ctxt->spaceNr = 0;
|
||||||
ctxt->spaceMax = 0;
|
ctxt->spaceMax = 0;
|
||||||
ctxt->space = NULL;
|
ctxt->space = NULL;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->spaceNr = 1;
|
ctxt->spaceNr = 1;
|
||||||
ctxt->spaceMax = 10;
|
ctxt->spaceMax = 10;
|
||||||
@ -2305,6 +2308,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
||||||
ctxt->catalogs = NULL;
|
ctxt->catalogs = NULL;
|
||||||
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2370,7 +2374,10 @@ xmlNewParserCtxt()
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
memset(ctxt, 0, sizeof(xmlParserCtxt));
|
memset(ctxt, 0, sizeof(xmlParserCtxt));
|
||||||
xmlInitParserCtxt(ctxt);
|
if (xmlInitParserCtxt(ctxt) < 0) {
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
return(ctxt);
|
return(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
183
testOOM.c
Normal file
183
testOOM.c
Normal file
@ -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);
|
||||||
|
}
|
260
testOOMlib.c
Normal file
260
testOOMlib.c
Normal file
@ -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;
|
||||||
|
}
|
26
testOOMlib.h
Normal file
26
testOOMlib.h
Normal file
@ -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
|
28
tree.c
28
tree.c
@ -193,6 +193,7 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
|
|||||||
xmlChar *ret = NULL;
|
xmlChar *ret = NULL;
|
||||||
|
|
||||||
*prefix = NULL;
|
*prefix = NULL;
|
||||||
|
if (name == NULL) return(NULL);
|
||||||
|
|
||||||
#ifndef XML_XML_NAMESPACE
|
#ifndef XML_XML_NAMESPACE
|
||||||
/* xml: prefix is not really a namespace */
|
/* xml: prefix is not really a namespace */
|
||||||
@ -216,7 +217,21 @@ xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
*prefix = xmlStrndup(name, len);
|
*prefix = xmlStrndup(name, len);
|
||||||
|
if (*prefix == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlSplitQName2 : out of memory!\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
ret = xmlStrdup(&name[len + 1]);
|
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);
|
return(ret);
|
||||||
}
|
}
|
||||||
@ -1670,6 +1685,7 @@ xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
|
|||||||
if (cur == NULL) {
|
if (cur == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlNewNsPropEatName : malloc failed\n");
|
"xmlNewNsPropEatName : malloc failed\n");
|
||||||
|
xmlFree(name);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
memset(cur, 0, sizeof(xmlAttr));
|
memset(cur, 0, sizeof(xmlAttr));
|
||||||
@ -1988,6 +2004,7 @@ xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
|
|||||||
if (cur == NULL) {
|
if (cur == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlNewNode : malloc failed\n");
|
"xmlNewNode : malloc failed\n");
|
||||||
|
xmlFree(name);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
memset(cur, 0, sizeof(xmlNode));
|
memset(cur, 0, sizeof(xmlNode));
|
||||||
@ -6047,11 +6064,13 @@ xmlIsBlankNode(xmlNodePtr node) {
|
|||||||
* @len: @content length
|
* @len: @content length
|
||||||
*
|
*
|
||||||
* Concat the given string at the end of the existing node content
|
* 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) {
|
xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
|
||||||
if (node == NULL) return;
|
if (node == NULL) return(-1);
|
||||||
|
|
||||||
if ((node->type != XML_TEXT_NODE) &&
|
if ((node->type != XML_TEXT_NODE) &&
|
||||||
(node->type != XML_CDATA_SECTION_NODE)) {
|
(node->type != XML_CDATA_SECTION_NODE)) {
|
||||||
@ -6059,9 +6078,12 @@ xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
|
|||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlTextConcat: node is not text nor CDATA\n");
|
"xmlTextConcat: node is not text nor CDATA\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
node->content = xmlStrncat(node->content, content, len);
|
node->content = xmlStrncat(node->content, content, len);
|
||||||
|
if (node->content == NULL)
|
||||||
|
return(-1);
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
3
uri.c
3
uri.c
@ -1992,6 +1992,9 @@ xmlCanonicPath(const xmlChar *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uri = xmlCreateURI();
|
uri = xmlCreateURI();
|
||||||
|
if (uri == NULL) {
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
len = xmlStrlen(path);
|
len = xmlStrlen(path);
|
||||||
|
83
valid.c
83
valid.c
@ -59,24 +59,27 @@ typedef struct _xmlValidState {
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
|
vstateVPush(xmlValidCtxtPtr ctxt, xmlElementPtr elemDecl, xmlNodePtr node) {
|
||||||
if (ctxt->vstateMax == 0) {
|
if ((ctxt->vstateMax == 0) || (ctxt->vstateTab == NULL)) {
|
||||||
ctxt->vstateMax = 10;
|
ctxt->vstateMax = 10;
|
||||||
ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
|
ctxt->vstateTab = (xmlValidState *) xmlMalloc(ctxt->vstateMax *
|
||||||
sizeof(ctxt->vstateTab[0]));
|
sizeof(ctxt->vstateTab[0]));
|
||||||
if (ctxt->vstateTab == NULL) {
|
if (ctxt->vstateTab == NULL) {
|
||||||
VERROR(ctxt->userData, "realloc failed !n");
|
VERROR(ctxt->userData, "malloc failed !n");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxt->vstateNr >= ctxt->vstateMax) {
|
if (ctxt->vstateNr >= ctxt->vstateMax) {
|
||||||
ctxt->vstateMax *= 2;
|
xmlValidState *tmp;
|
||||||
ctxt->vstateTab = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
|
|
||||||
ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
|
tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
|
||||||
if (ctxt->vstateTab == NULL) {
|
2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
|
||||||
|
if (tmp == NULL) {
|
||||||
VERROR(ctxt->userData, "realloc failed !n");
|
VERROR(ctxt->userData, "realloc failed !n");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
ctxt->vstateMax *= 2;
|
||||||
|
ctxt->vstateTab = tmp;
|
||||||
}
|
}
|
||||||
ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
|
ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr];
|
||||||
ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
|
ctxt->vstateTab[ctxt->vstateNr].elemDecl = elemDecl;
|
||||||
@ -161,15 +164,28 @@ vstateVPush(xmlValidCtxtPtr ctxt, xmlElementContentPtr cont,
|
|||||||
if (ctxt->vstateNr > MAX_RECURSE) {
|
if (ctxt->vstateNr > MAX_RECURSE) {
|
||||||
return(-1);
|
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) {
|
if (ctxt->vstateNr >= ctxt->vstateMax) {
|
||||||
ctxt->vstateMax *= 2;
|
xmlValidState *tmp;
|
||||||
ctxt->vstateTab = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
|
|
||||||
ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
|
tmp = (xmlValidState *) xmlRealloc(ctxt->vstateTab,
|
||||||
if (ctxt->vstateTab == NULL) {
|
2 * ctxt->vstateMax * sizeof(ctxt->vstateTab[0]));
|
||||||
|
if (tmp == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"realloc failed !n");
|
"realloc failed !n");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
ctxt->vstateMax *= 2;
|
||||||
|
ctxt->vstateTab = tmp;
|
||||||
ctxt->vstate = &ctxt->vstateTab[0];
|
ctxt->vstate = &ctxt->vstateTab[0];
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -219,15 +235,15 @@ nodeVPush(xmlValidCtxtPtr ctxt, xmlNodePtr value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctxt->nodeNr >= ctxt->nodeMax) {
|
if (ctxt->nodeNr >= ctxt->nodeMax) {
|
||||||
ctxt->nodeMax *= 2;
|
xmlNodePtr *tmp;
|
||||||
ctxt->nodeTab =
|
tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
|
||||||
(xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
|
ctxt->nodeMax * 2 * sizeof(ctxt->nodeTab[0]));
|
||||||
ctxt->nodeMax *
|
if (tmp == NULL) {
|
||||||
sizeof(ctxt->nodeTab[0]));
|
|
||||||
if (ctxt->nodeTab == NULL) {
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
|
xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
ctxt->nodeMax *= 2;
|
||||||
|
ctxt->nodeTab = tmp;
|
||||||
}
|
}
|
||||||
ctxt->nodeTab[ctxt->nodeNr] = value;
|
ctxt->nodeTab[ctxt->nodeNr] = value;
|
||||||
ctxt->node = value;
|
ctxt->node = value;
|
||||||
@ -635,7 +651,7 @@ xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
|
|||||||
xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
|
xmlValidBuildAContentModel(elem->content, ctxt, elem->name);
|
||||||
xmlAutomataSetFinalState(ctxt->am, ctxt->state);
|
xmlAutomataSetFinalState(ctxt->am, ctxt->state);
|
||||||
elem->contModel = xmlAutomataCompile(ctxt->am);
|
elem->contModel = xmlAutomataCompile(ctxt->am);
|
||||||
if (!xmlRegexpIsDeterminist(elem->contModel)) {
|
if (xmlRegexpIsDeterminist(elem->contModel) != 1) {
|
||||||
char expr[5000];
|
char expr[5000];
|
||||||
expr[0] = 0;
|
expr[0] = 0;
|
||||||
xmlSnprintfElementContent(expr, 5000, elem->content, 1);
|
xmlSnprintfElementContent(expr, 5000, elem->content, 1);
|
||||||
@ -901,7 +917,8 @@ xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int
|
|||||||
strcat(buf, " ...");
|
strcat(buf, " ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strcat(buf, (char *) content->name);
|
if (content->name != NULL)
|
||||||
|
strcat(buf, (char *) content->name);
|
||||||
break;
|
break;
|
||||||
case XML_ELEMENT_CONTENT_SEQ:
|
case XML_ELEMENT_CONTENT_SEQ:
|
||||||
if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
||||||
@ -1086,6 +1103,10 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlAddElementDecl: Table creation failed!\n");
|
"xmlAddElementDecl: Table creation failed!\n");
|
||||||
|
if (uqname != NULL)
|
||||||
|
xmlFree(uqname);
|
||||||
|
if (ns != NULL)
|
||||||
|
xmlFree(ns);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,6 +1137,8 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
VERROR(ctxt->userData, "Redefinition of element %s\n", name);
|
VERROR(ctxt->userData, "Redefinition of element %s\n", name);
|
||||||
if (uqname != NULL)
|
if (uqname != NULL)
|
||||||
xmlFree(uqname);
|
xmlFree(uqname);
|
||||||
|
if (ns != NULL)
|
||||||
|
xmlFree(ns);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1123,6 +1146,10 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlAddElementDecl: out of memory\n");
|
"xmlAddElementDecl: out of memory\n");
|
||||||
|
if (uqname != NULL)
|
||||||
|
xmlFree(uqname);
|
||||||
|
if (ns != NULL)
|
||||||
|
xmlFree(ns);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
memset(ret, 0, sizeof(xmlElement));
|
memset(ret, 0, sizeof(xmlElement));
|
||||||
@ -1132,6 +1159,16 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
|||||||
* fill the structure.
|
* fill the structure.
|
||||||
*/
|
*/
|
||||||
ret->name = xmlStrdup(name);
|
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;
|
ret->prefix = ns;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2667,7 +2704,7 @@ xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
|
|||||||
xmlElementPtr cur;
|
xmlElementPtr cur;
|
||||||
xmlChar *uqname = NULL, *prefix = NULL;
|
xmlChar *uqname = NULL, *prefix = NULL;
|
||||||
|
|
||||||
if (dtd == NULL) return(NULL);
|
if ((dtd == NULL) || (name == NULL)) return(NULL);
|
||||||
if (dtd->elements == NULL)
|
if (dtd->elements == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
table = (xmlElementTablePtr) dtd->elements;
|
table = (xmlElementTablePtr) dtd->elements;
|
||||||
@ -4641,7 +4678,7 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
|||||||
if (elemDecl->contModel == NULL)
|
if (elemDecl->contModel == NULL)
|
||||||
ret = xmlValidBuildContentModel(ctxt, elemDecl);
|
ret = xmlValidBuildContentModel(ctxt, elemDecl);
|
||||||
if (elemDecl->contModel == NULL) {
|
if (elemDecl->contModel == NULL) {
|
||||||
ret = -1;
|
return(-1);
|
||||||
} else {
|
} else {
|
||||||
xmlRegExecCtxtPtr exec;
|
xmlRegExecCtxtPtr exec;
|
||||||
|
|
||||||
@ -4837,14 +4874,14 @@ fail:
|
|||||||
char list[5000];
|
char list[5000];
|
||||||
|
|
||||||
expr[0] = 0;
|
expr[0] = 0;
|
||||||
xmlSnprintfElementContent(expr, 5000, cont, 1);
|
xmlSnprintfElementContent(&expr[0], 5000, cont, 1);
|
||||||
list[0] = 0;
|
list[0] = 0;
|
||||||
#ifndef LIBXML_REGEXP_ENABLED
|
#ifndef LIBXML_REGEXP_ENABLED
|
||||||
if (repl != NULL)
|
if (repl != NULL)
|
||||||
xmlSnprintfElements(list, 5000, repl, 1);
|
xmlSnprintfElements(&list[0], 5000, repl, 1);
|
||||||
else
|
else
|
||||||
#endif /* LIBXML_REGEXP_ENABLED */
|
#endif /* LIBXML_REGEXP_ENABLED */
|
||||||
xmlSnprintfElements(list, 5000, child, 1);
|
xmlSnprintfElements(&list[0], 5000, child, 1);
|
||||||
|
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
if (parent != NULL) VECTXT(ctxt, parent);
|
if (parent != NULL) VECTXT(ctxt, parent);
|
||||||
|
@ -305,6 +305,8 @@ xmlReallocLoc(void *ptr,size_t size, const char * file, int line)
|
|||||||
unsigned long number;
|
unsigned long number;
|
||||||
|
|
||||||
if (!xmlMemInitialized) xmlInitMemory();
|
if (!xmlMemInitialized) xmlInitMemory();
|
||||||
|
if (ptr == NULL)
|
||||||
|
return(NULL);
|
||||||
TEST_POINT
|
TEST_POINT
|
||||||
|
|
||||||
p = CLIENT_2_HDR(ptr);
|
p = CLIENT_2_HDR(ptr);
|
||||||
|
12
xmlreader.c
12
xmlreader.c
@ -83,7 +83,8 @@ typedef enum {
|
|||||||
XML_TEXTREADER_END= 2,
|
XML_TEXTREADER_END= 2,
|
||||||
XML_TEXTREADER_EMPTY= 3,
|
XML_TEXTREADER_EMPTY= 3,
|
||||||
XML_TEXTREADER_BACKTRACK= 4,
|
XML_TEXTREADER_BACKTRACK= 4,
|
||||||
XML_TEXTREADER_DONE= 5
|
XML_TEXTREADER_DONE= 5,
|
||||||
|
XML_TEXTREADER_ERROR= 6
|
||||||
} xmlTextReaderState;
|
} xmlTextReaderState;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -417,6 +418,7 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
|
|||||||
s, 1);
|
s, 1);
|
||||||
reader->cur = inbuf->use;
|
reader->cur = inbuf->use;
|
||||||
reader->mode = XML_TEXTREADER_DONE;
|
reader->mode = XML_TEXTREADER_DONE;
|
||||||
|
if (val != 0) return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader->state = oldstate;
|
reader->state = oldstate;
|
||||||
@ -1151,11 +1153,17 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
|
|||||||
ret->base = 0;
|
ret->base = 0;
|
||||||
ret->cur = 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->_private = ret;
|
||||||
ret->ctxt->linenumbers = 1;
|
ret->ctxt->linenumbers = 1;
|
||||||
ret->allocs = XML_TEXTREADER_CTXT;
|
ret->allocs = XML_TEXTREADER_CTXT;
|
||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
165
xmlregexp.c
165
xmlregexp.c
@ -332,23 +332,19 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
xmlRegexpPtr ret;
|
xmlRegexpPtr ret;
|
||||||
|
|
||||||
ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
|
ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
|
||||||
if (ret == NULL)
|
if (ret == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"out of memory compiling regexp\n");
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
}
|
||||||
memset(ret, 0, sizeof(xmlRegexp));
|
memset(ret, 0, sizeof(xmlRegexp));
|
||||||
ret->string = ctxt->string;
|
ret->string = ctxt->string;
|
||||||
ctxt->string = NULL;
|
|
||||||
ret->nbStates = ctxt->nbStates;
|
ret->nbStates = ctxt->nbStates;
|
||||||
ctxt->nbStates = 0;
|
|
||||||
ret->states = ctxt->states;
|
ret->states = ctxt->states;
|
||||||
ctxt->states = NULL;
|
|
||||||
ret->nbAtoms = ctxt->nbAtoms;
|
ret->nbAtoms = ctxt->nbAtoms;
|
||||||
ctxt->nbAtoms = 0;
|
|
||||||
ret->atoms = ctxt->atoms;
|
ret->atoms = ctxt->atoms;
|
||||||
ctxt->atoms = NULL;
|
|
||||||
ret->nbCounters = ctxt->nbCounters;
|
ret->nbCounters = ctxt->nbCounters;
|
||||||
ctxt->nbCounters = 0;
|
|
||||||
ret->counters = ctxt->counters;
|
ret->counters = ctxt->counters;
|
||||||
ctxt->counters = NULL;
|
|
||||||
ret->determinist = ctxt->determinist;
|
ret->determinist = ctxt->determinist;
|
||||||
|
|
||||||
if ((ret->determinist != 0) &&
|
if ((ret->determinist != 0) &&
|
||||||
@ -373,6 +369,12 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
|
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++) {
|
for (i = 0;i < ret->nbStates;i++) {
|
||||||
if (ret->states[i] != NULL) {
|
if (ret->states[i] != NULL) {
|
||||||
stateRemap[i] = nbstates;
|
stateRemap[i] = nbstates;
|
||||||
@ -385,7 +387,22 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
printf("Final: %d states\n", nbstates);
|
printf("Final: %d states\n", nbstates);
|
||||||
#endif
|
#endif
|
||||||
stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
|
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));
|
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++) {
|
for (i = 0;i < ret->nbAtoms;i++) {
|
||||||
if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
|
if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
|
||||||
(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
|
(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
|
||||||
@ -399,6 +416,15 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
if (j >= nbatoms) {
|
if (j >= nbatoms) {
|
||||||
stringRemap[i] = nbatoms;
|
stringRemap[i] = nbatoms;
|
||||||
stringMap[nbatoms] = xmlStrdup(value);
|
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++;
|
nbatoms++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -407,20 +433,29 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
for (i = 0;i < nbatoms;i++)
|
for (i = 0;i < nbatoms;i++)
|
||||||
xmlFree(stringMap[i]);
|
xmlFree(stringMap[i]);
|
||||||
xmlFree(stringMap);
|
xmlFree(stringMap);
|
||||||
goto fail_compact;
|
xmlFree(ret);
|
||||||
|
return(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_COMPACTION
|
#ifdef DEBUG_COMPACTION
|
||||||
printf("Final: %d atoms\n", nbatoms);
|
printf("Final: %d atoms\n", nbatoms);
|
||||||
#endif
|
#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
|
* Allocate the transition table. The first entry for each
|
||||||
* state correspond to the state type.
|
* state correspond to the state type.
|
||||||
*/
|
*/
|
||||||
transitions = (int *) xmlMalloc(nbstates * (nbatoms + 1) * sizeof(int));
|
|
||||||
transdata = NULL;
|
transdata = NULL;
|
||||||
memset(transitions, 0, nbstates * (nbatoms + 1) * sizeof(int));
|
|
||||||
|
|
||||||
for (i = 0;i < ret->nbStates;i++) {
|
for (i = 0;i < ret->nbStates;i++) {
|
||||||
int stateno, atomno, targetno, prev;
|
int stateno, atomno, targetno, prev;
|
||||||
@ -445,6 +480,11 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
if (transdata != NULL)
|
if (transdata != NULL)
|
||||||
memset(transdata, 0,
|
memset(transdata, 0,
|
||||||
nbstates * nbatoms * sizeof(void *));
|
nbstates * nbatoms * sizeof(void *));
|
||||||
|
else {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"out of memory compiling regexp\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
targetno = stateRemap[trans->to];
|
targetno = stateRemap[trans->to];
|
||||||
/*
|
/*
|
||||||
@ -470,7 +510,7 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
for (i = 0;i < nbatoms;i++)
|
for (i = 0;i < nbatoms;i++)
|
||||||
xmlFree(stringMap[i]);
|
xmlFree(stringMap[i]);
|
||||||
xmlFree(stringMap);
|
xmlFree(stringMap);
|
||||||
goto fail_compact;
|
goto not_determ;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if 0
|
#if 0
|
||||||
@ -524,7 +564,14 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|||||||
xmlFree(stateRemap);
|
xmlFree(stateRemap);
|
||||||
xmlFree(stringRemap);
|
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);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,11 +1095,11 @@ xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
|
|||||||
return(ctxt->nbCounters++);
|
return(ctxt->nbCounters++);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
|
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
|
||||||
if (atom == NULL) {
|
if (atom == NULL) {
|
||||||
ERROR("atom push: atom is NULL");
|
ERROR("atom push: atom is NULL");
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
if (ctxt->maxAtoms == 0) {
|
if (ctxt->maxAtoms == 0) {
|
||||||
ctxt->maxAtoms = 4;
|
ctxt->maxAtoms = 4;
|
||||||
@ -1061,7 +1108,7 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
|
|||||||
if (ctxt->atoms == NULL) {
|
if (ctxt->atoms == NULL) {
|
||||||
ERROR("atom push: allocation failed");
|
ERROR("atom push: allocation failed");
|
||||||
ctxt->maxAtoms = 0;
|
ctxt->maxAtoms = 0;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
} else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
|
} else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
|
||||||
xmlRegAtomPtr *tmp;
|
xmlRegAtomPtr *tmp;
|
||||||
@ -1071,12 +1118,13 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
|
|||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
ERROR("atom push: allocation failed");
|
ERROR("atom push: allocation failed");
|
||||||
ctxt->maxAtoms /= 2;
|
ctxt->maxAtoms /= 2;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->atoms = tmp;
|
ctxt->atoms = tmp;
|
||||||
}
|
}
|
||||||
atom->no = ctxt->nbAtoms;
|
atom->no = ctxt->nbAtoms;
|
||||||
ctxt->atoms[ctxt->nbAtoms++] = atom;
|
ctxt->atoms[ctxt->nbAtoms++] = atom;
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1132,8 +1180,9 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
|
|||||||
state->nbTrans++;
|
state->nbTrans++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
|
xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
|
||||||
|
if (state == NULL) return(-1);
|
||||||
if (ctxt->maxStates == 0) {
|
if (ctxt->maxStates == 0) {
|
||||||
ctxt->maxStates = 4;
|
ctxt->maxStates = 4;
|
||||||
ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
|
ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
|
||||||
@ -1141,7 +1190,7 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
|
|||||||
if (ctxt->states == NULL) {
|
if (ctxt->states == NULL) {
|
||||||
ERROR("add range: allocation failed");
|
ERROR("add range: allocation failed");
|
||||||
ctxt->maxStates = 0;
|
ctxt->maxStates = 0;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
} else if (ctxt->nbStates >= ctxt->maxStates) {
|
} else if (ctxt->nbStates >= ctxt->maxStates) {
|
||||||
xmlRegStatePtr *tmp;
|
xmlRegStatePtr *tmp;
|
||||||
@ -1151,12 +1200,13 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
|
|||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
ERROR("add range: allocation failed");
|
ERROR("add range: allocation failed");
|
||||||
ctxt->maxStates /= 2;
|
ctxt->maxStates /= 2;
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
ctxt->states = tmp;
|
ctxt->states = tmp;
|
||||||
}
|
}
|
||||||
state->no = ctxt->nbStates;
|
state->no = ctxt->nbStates;
|
||||||
ctxt->states[ctxt->nbStates++] = state;
|
ctxt->states[ctxt->nbStates++] = state;
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1245,20 +1295,23 @@ xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,
|
|||||||
* @to: the target state or NULL for building a new one
|
* @to: the target state or NULL for building a new one
|
||||||
* @atom: the atom generating the transition
|
* @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,
|
xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
|
||||||
xmlRegStatePtr to, xmlRegAtomPtr atom) {
|
xmlRegStatePtr to, xmlRegAtomPtr atom) {
|
||||||
if (atom == NULL) {
|
if (atom == NULL) {
|
||||||
ERROR("genrate transition: atom == NULL");
|
ERROR("genrate transition: atom == NULL");
|
||||||
return;
|
return(-1);
|
||||||
}
|
}
|
||||||
if (atom->type == XML_REGEXP_SUBREG) {
|
if (atom->type == XML_REGEXP_SUBREG) {
|
||||||
/*
|
/*
|
||||||
* this is a subexpression handling one should not need to
|
* this is a subexpression handling one should not need to
|
||||||
* create a new node excep for XML_REGEXP_QUANT_RANGE.
|
* 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) &&
|
if ((to != NULL) && (atom->stop != to) &&
|
||||||
(atom->quant != XML_REGEXP_QUANT_RANGE)) {
|
(atom->quant != XML_REGEXP_QUANT_RANGE)) {
|
||||||
/*
|
/*
|
||||||
@ -1314,14 +1367,20 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return(0);
|
||||||
} else {
|
} else {
|
||||||
if (to == NULL) {
|
if (to == NULL) {
|
||||||
to = xmlRegNewState(ctxt);
|
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);
|
xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
|
||||||
xmlRegAtomPush(ctxt, atom);
|
|
||||||
ctxt->state = to;
|
ctxt->state = to;
|
||||||
}
|
}
|
||||||
switch (atom->quant) {
|
switch (atom->quant) {
|
||||||
@ -1341,6 +1400,7 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1433,6 +1493,9 @@ xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
|
|||||||
int statenr, transnr;
|
int statenr, transnr;
|
||||||
xmlRegStatePtr state;
|
xmlRegStatePtr state;
|
||||||
|
|
||||||
|
if (ctxt->states == NULL) return;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* build the completed transitions bypassing the epsilons
|
* build the completed transitions bypassing the epsilons
|
||||||
* Use a marking algorithm to avoid loops
|
* Use a marking algorithm to avoid loops
|
||||||
@ -2276,6 +2339,8 @@ xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
|
|||||||
|
|
||||||
if (comp == NULL)
|
if (comp == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
if ((comp->compact == NULL) && (comp->states == NULL))
|
||||||
|
return(NULL);
|
||||||
exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
|
exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
|
||||||
if (exec == NULL) {
|
if (exec == NULL) {
|
||||||
return(NULL);
|
return(NULL);
|
||||||
@ -3568,6 +3633,8 @@ xmlFAParseCharClass(xmlRegParserCtxtPtr ctxt) {
|
|||||||
* @ctxt: a regexp parser context
|
* @ctxt: a regexp parser context
|
||||||
*
|
*
|
||||||
* [8] QuantExact ::= [0-9]+
|
* [8] QuantExact ::= [0-9]+
|
||||||
|
*
|
||||||
|
* Returns 0 if success or -1 in case of error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
|
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
|
||||||
@ -3723,8 +3790,9 @@ xmlFAParsePiece(xmlRegParserCtxtPtr ctxt) {
|
|||||||
* @first: is taht the first
|
* @first: is taht the first
|
||||||
*
|
*
|
||||||
* [2] branch ::= piece*
|
* [2] branch ::= piece*
|
||||||
|
8
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
|
xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
|
||||||
xmlRegStatePtr previous;
|
xmlRegStatePtr previous;
|
||||||
xmlRegAtomPtr prevatom = NULL;
|
xmlRegAtomPtr prevatom = NULL;
|
||||||
@ -3734,7 +3802,8 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
|
|||||||
ret = xmlFAParsePiece(ctxt);
|
ret = xmlFAParsePiece(ctxt);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (first) {
|
if (first) {
|
||||||
xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
|
if (xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom) < 0)
|
||||||
|
return(-1);
|
||||||
previous = ctxt->state;
|
previous = ctxt->state;
|
||||||
} else {
|
} else {
|
||||||
prevatom = ctxt->atom;
|
prevatom = ctxt->atom;
|
||||||
@ -3745,9 +3814,13 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
|
|||||||
ret = xmlFAParsePiece(ctxt);
|
ret = xmlFAParsePiece(ctxt);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (first) {
|
if (first) {
|
||||||
xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
|
if (xmlFAGenerateTransitions(ctxt, previous, NULL,
|
||||||
|
ctxt->atom) < 0)
|
||||||
|
return(-1);
|
||||||
} else {
|
} else {
|
||||||
xmlFAGenerateTransitions(ctxt, previous, NULL, prevatom);
|
if (xmlFAGenerateTransitions(ctxt, previous, NULL,
|
||||||
|
prevatom) < 0)
|
||||||
|
return(-1);
|
||||||
prevatom = ctxt->atom;
|
prevatom = ctxt->atom;
|
||||||
}
|
}
|
||||||
previous = ctxt->state;
|
previous = ctxt->state;
|
||||||
@ -3755,8 +3828,10 @@ xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!first) {
|
if (!first) {
|
||||||
xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom);
|
if (xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom) < 0)
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3994,7 +4069,15 @@ xmlNewAutomata(void) {
|
|||||||
/* initialize the parser */
|
/* initialize the parser */
|
||||||
ctxt->end = NULL;
|
ctxt->end = NULL;
|
||||||
ctxt->start = ctxt->state = xmlRegNewState(ctxt);
|
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);
|
return(ctxt);
|
||||||
}
|
}
|
||||||
@ -4067,12 +4150,17 @@ xmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from,
|
|||||||
if ((am == NULL) || (from == NULL) || (token == NULL))
|
if ((am == NULL) || (from == NULL) || (token == NULL))
|
||||||
return(NULL);
|
return(NULL);
|
||||||
atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
|
atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
|
||||||
|
if (atom == NULL)
|
||||||
|
return(NULL);
|
||||||
atom->data = data;
|
atom->data = data;
|
||||||
if (atom == NULL)
|
if (atom == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
atom->valuep = xmlStrdup(token);
|
atom->valuep = xmlStrdup(token);
|
||||||
|
|
||||||
xmlFAGenerateTransitions(am, from, to, atom);
|
if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
|
||||||
|
xmlRegFreeAtom(atom);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
if (to == NULL)
|
if (to == NULL)
|
||||||
return(am->state);
|
return(am->state);
|
||||||
return(to);
|
return(to);
|
||||||
@ -4127,7 +4215,10 @@ xmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from,
|
|||||||
atom->valuep = str;
|
atom->valuep = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlFAGenerateTransitions(am, from, to, atom);
|
if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
|
||||||
|
xmlRegFreeAtom(atom);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
if (to == NULL)
|
if (to == NULL)
|
||||||
return(am->state);
|
return(am->state);
|
||||||
return(to);
|
return(to);
|
||||||
@ -4173,7 +4264,10 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
|
|||||||
atom->min = min;
|
atom->min = min;
|
||||||
atom->max = max;
|
atom->max = max;
|
||||||
|
|
||||||
xmlFAGenerateTransitions(am, from, to, atom);
|
if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
|
||||||
|
xmlRegFreeAtom(atom);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
if (to == NULL)
|
if (to == NULL)
|
||||||
to = am->state;
|
to = am->state;
|
||||||
if (to == NULL)
|
if (to == NULL)
|
||||||
@ -4400,6 +4494,7 @@ xmlRegexpPtr
|
|||||||
xmlAutomataCompile(xmlAutomataPtr am) {
|
xmlAutomataCompile(xmlAutomataPtr am) {
|
||||||
xmlRegexpPtr ret;
|
xmlRegexpPtr ret;
|
||||||
|
|
||||||
|
if ((am == NULL) || (am->error != 0)) return(NULL);
|
||||||
xmlFAEliminateEpsilonTransitions(am);
|
xmlFAEliminateEpsilonTransitions(am);
|
||||||
/* xmlFAComputesDeterminism(am); */
|
/* xmlFAComputesDeterminism(am); */
|
||||||
ret = xmlRegEpxFromParse(am);
|
ret = xmlRegEpxFromParse(am);
|
||||||
|
Reference in New Issue
Block a user