removed an unprotedted debug message Aleksi Suhonen put a guard against
* python/libxml.c: removed an unprotedted debug message Aleksi Suhonen
* parser.c: put a guard against infinite document depth, basically
trying to avoid another kind of DoS attack.
* relaxng.c: some code w.r.t. nameClasses
Daniel
diff --git a/ChangeLog b/ChangeLog
index e730927..03047a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Mon Feb 3 09:50:26 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+ * python/libxml.c: removed an unprotedted debug message Aleksi Suhonen
+ * parser.c: put a guard against infinite document depth, basically
+ trying to avoid another kind of DoS attack.
+ * relaxng.c: some code w.r.t. nameClasses
+
Sun Feb 2 17:01:43 CET 2003 Daniel Veillard <daniel@veillard.com>
* test/relaxng/* result/relaxng/*: check all the namespace support
diff --git a/parser.c b/parser.c
index f05c64f..3392c85 100644
--- a/parser.c
+++ b/parser.c
@@ -76,6 +76,14 @@
#include <zlib.h>
#endif
+/**
+ * MAX_DEPTH:
+ *
+ * arbitrary depth limit for the XML documents that we allow to
+ * process. This is not a limitation of the parser but a safety
+ * boundary feature.
+ */
+#define MAX_DEPTH 1024
#define XML_PARSER_BIG_BUFFER_SIZE 300
#define XML_PARSER_BUFFER_SIZE 100
@@ -191,6 +199,18 @@
return (0);
}
}
+#ifdef MAX_DEPTH
+ if (ctxt->nodeNr > MAX_DEPTH) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ ctxt->sax->error(ctxt->userData,
+ "Excessive depth in document: change MAX_DEPTH = %d\n",
+ MAX_DEPTH);
+ ctxt->wellFormed = 0;
+ ctxt->instate = XML_PARSER_EOF;
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ return(0);
+ }
+#endif
ctxt->nodeTab[ctxt->nodeNr] = value;
ctxt->node = value;
return (ctxt->nodeNr++);
diff --git a/python/libxml.c b/python/libxml.c
index 0603950..f7b752f 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -2527,7 +2527,9 @@
if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
return (NULL);
node = (xmlNodePtr) xmlNewNode(NULL, name);
+#ifdef DEBUG
printf("NewNode: %s : %p\n", name, (void *) node);
+#endif
if (node == NULL) {
Py_INCREF(Py_None);
diff --git a/relaxng.c b/relaxng.c
index 220edba..c3fe55c 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -123,6 +123,7 @@
xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
xmlRelaxNGDefinePtr next; /* list within grouping sequences */
xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
+ xmlRelaxNGDefinePtr nameClass;/* the nameClass definition if any */
xmlRelaxNGDefinePtr nextHash;/* next define in defs/refs hash tables */
};
@@ -1562,6 +1563,9 @@
xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
static int xmlRelaxNGParseGrammarContent(
xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes);
+static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(
+ xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
+ xmlRelaxNGDefinePtr def);
#define IS_BLANK_NODE(n) \
@@ -2420,7 +2424,6 @@
xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
xmlRelaxNGDefinePtr ret, cur, last;
xmlNodePtr child;
- xmlChar *val;
int old_flags;
ret = xmlRelaxNGNewDefine(ctxt, node);
@@ -2438,27 +2441,10 @@
}
old_flags = ctxt->flags;
ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
- if (IS_RELAXNG(child, "name")) {
- val = xmlNodeGetContent(child);
- ret->name = val;
- val = xmlGetProp(child, BAD_CAST "ns");
- ret->ns = val;
- } else if (IS_RELAXNG(child, "anyName")) {
- TODO
- } else if (IS_RELAXNG(child, "nsName")) {
- TODO
- } else if (IS_RELAXNG(child, "choice")) {
- TODO
- } else {
- if (ctxt->error != NULL)
- ctxt->error(ctxt->userData,
- "element: expecting name, anyName, nsName or choice : got %s\n",
- child->name);
- ctxt->nbErrors++;
- ctxt->flags = old_flags;
- return(ret);
- }
- child = child->next;
+ cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
+ if (cur != NULL)
+ child = child->next;
+
last = NULL;
while (child != NULL) {
cur = xmlRelaxNGParsePattern(ctxt, child);
@@ -2515,6 +2501,75 @@
}
/**
+ * xmlRelaxNGParseExceptNameClass:
+ * @ctxt: a Relax-NG parser context
+ * @node: the except node
+ *
+ * parse the content of a RelaxNG nameClass node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
+ TODO
+ return(NULL);
+}
+
+/**
+ * xmlRelaxNGParseNameClass:
+ * @ctxt: a Relax-NG parser context
+ * @node: the nameClass node
+ * @def: the current definition
+ *
+ * parse the content of a RelaxNG nameClass node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
+ xmlRelaxNGDefinePtr def) {
+ xmlRelaxNGDefinePtr ret = def;
+ xmlChar *val;
+
+ if (IS_RELAXNG(node, "name")) {
+ val = xmlNodeGetContent(node);
+ ret->name = val;
+ val = xmlGetProp(node, BAD_CAST "ns");
+ ret->ns = val;
+ } else if (IS_RELAXNG(node, "anyName")) {
+ ret->name = NULL;
+ ret->ns = NULL;
+ if (node->children != NULL) {
+ ret->nameClass =
+ xmlRelaxNGParseExceptNameClass(ctxt, node->children);
+ }
+ } else if (IS_RELAXNG(node, "nsName")) {
+ ret->name = NULL;
+ ret->ns = xmlGetProp(node, BAD_CAST "ns");
+ if (ret->ns == NULL) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "nsName has no ns attribute\n");
+ ctxt->nbErrors++;
+ }
+ if (node->children != NULL) {
+ ret->nameClass =
+ xmlRelaxNGParseExceptNameClass(ctxt, node->children);
+ }
+ } else if (IS_RELAXNG(node, "choice")) {
+ TODO
+ } else {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "expecting name, anyName, nsName or choice : got %s\n",
+ node->name);
+ ctxt->nbErrors++;
+ return(NULL);
+ }
+ return(ret);
+}
+
+/**
* xmlRelaxNGParseElement:
* @ctxt: a Relax-NG parser context
* @node: the element node
@@ -2527,7 +2582,6 @@
xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
xmlRelaxNGDefinePtr ret, cur, last;
xmlNodePtr child;
- xmlChar *val;
const xmlChar *olddefine;
ret = xmlRelaxNGNewDefine(ctxt, node);
@@ -2543,26 +2597,10 @@
ctxt->nbErrors++;
return(ret);
}
- if (IS_RELAXNG(child, "name")) {
- val = xmlNodeGetContent(child);
- ret->name = val;
- val = xmlGetProp(child, BAD_CAST "ns");
- ret->ns = val;
- } else if (IS_RELAXNG(child, "anyName")) {
- TODO
- } else if (IS_RELAXNG(child, "nsName")) {
- TODO
- } else if (IS_RELAXNG(child, "choice")) {
- TODO
- } else {
- if (ctxt->error != NULL)
- ctxt->error(ctxt->userData,
- "element: expecting name, anyName, nsName or choice : got %s\n",
- child->name);
- ctxt->nbErrors++;
- return(ret);
- }
- child = child->next;
+ cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
+ if (cur != NULL)
+ child = child->next;
+
if (child == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
@@ -3405,12 +3443,7 @@
text = text->next;
}
}
- if (text == NULL) {
- if (ctxt->error != NULL)
- ctxt->error(ctxt->userData,
- "xmlRelaxNGParse: attribute without name\n");
- ctxt->nbErrors++;
- } else {
+ if (text != NULL) {
xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
}
}
@@ -4294,8 +4327,70 @@
xmlGenericError(xmlGenericErrorContext,
"xmlRelaxNGValidateAttribute(%s): %d\n", define->name, ret);
#endif
+ } else if (define->ns != NULL) {
+ for (i = 0;i < ctxt->state->nbAttrs;i++) {
+ tmp = ctxt->state->attrs[i];
+ if ((tmp != NULL) && (tmp->ns != NULL) &&
+ (xmlStrEqual(define->ns, tmp->ns->href))) {
+ prop = tmp;
+ break;
+ }
+ }
+ if (prop != NULL) {
+ value = xmlNodeListGetString(prop->doc, prop->children, 1);
+ oldvalue = ctxt->state->value;
+ ctxt->state->value = value;
+ ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
+ value = ctxt->state->value;
+ ctxt->state->value = oldvalue;
+ if (value != NULL)
+ xmlFree(value);
+ if (ret == 0) {
+ /*
+ * flag the attribute as processed
+ */
+ ctxt->state->attrs[i] = NULL;
+ }
+ } else {
+ ret = -1;
+ }
+#ifdef DEBUG
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
+ define->ns, ret);
+#endif
} else {
- TODO
+ for (i = 0;i < ctxt->state->nbAttrs;i++) {
+ tmp = ctxt->state->attrs[i];
+ if (tmp != NULL) {
+ prop = tmp;
+ break;
+ }
+ }
+ if (prop != NULL) {
+ value = xmlNodeListGetString(prop->doc, prop->children, 1);
+ oldvalue = ctxt->state->value;
+ ctxt->state->value = value;
+ ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
+ value = ctxt->state->value;
+ ctxt->state->value = oldvalue;
+ if (value != NULL)
+ xmlFree(value);
+ if (ret == 0) {
+ /*
+ * flag the attribute as processed
+ */
+ ctxt->state->attrs[i] = NULL;
+ }
+ } else {
+ ret = -1;
+ }
+#ifdef DEBUG
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGValidateAttribute(anyName): %d\n",
+ ret);
+#endif
+
}
return(ret);
@@ -4748,11 +4843,11 @@
node->name, define->ns);
return(-1);
}
- } else {
+ } else if (define->name != NULL) {
if (node->ns != NULL) {
VALID_CTXT();
VALID_ERROR("Expecting no namespace for element %s\n",
- node->name);
+ define->name);
return(-1);
}
}