fixing some nodeinfo in entities problem raised by Glenn W. Bach
* parser.c: fixing some nodeinfo in entities problem raised
by Glenn W. Bach
* relaxng.c: implemented the first section 7.3 check
* result/relaxng/*: updated the results
Daniel
diff --git a/relaxng.c b/relaxng.c
index eeb06b8..84ca17c 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -234,6 +234,7 @@
struct _xmlRelaxNGInterleaveGroup {
xmlRelaxNGDefinePtr rule; /* the rule to satisfy */
xmlRelaxNGDefinePtr *defs; /* the array of element definitions */
+ xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
};
/**
@@ -592,6 +593,8 @@
if (group != NULL) {
if (group->defs != NULL)
xmlFree(group->defs);
+ if (group->attrs != NULL)
+ xmlFree(group->attrs);
xmlFree(group);
}
}
@@ -2094,7 +2097,8 @@
/**
* xmlRelaxNGGetElements:
* @ctxt: a Relax-NG parser context
- * @def: the interleave definition
+ * @def: the definition definition
+ * @eora: gather elements (0) or attributes (1)
*
* Compute the list of top elements a definition can generate
*
@@ -2102,16 +2106,25 @@
*/
static xmlRelaxNGDefinePtr *
xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
- xmlRelaxNGDefinePtr def) {
+ xmlRelaxNGDefinePtr def,
+ int eora) {
xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
int len = 0;
int max = 0;
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return(NULL);
+
parent = NULL;
cur = def;
while (cur != NULL) {
- if ((cur->type == XML_RELAXNG_ELEMENT) ||
- (cur->type == XML_RELAXNG_TEXT)) {
+ if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
+ (cur->type == XML_RELAXNG_TEXT))) ||
+ ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) {
if (ret == NULL) {
max = 10;
ret = (xmlRelaxNGDefinePtr *)
@@ -2160,7 +2173,7 @@
}
}
if (cur == def)
- return(ret);
+ break;
if (cur->next != NULL) {
cur = cur->next;
continue;
@@ -2179,10 +2192,92 @@
}
/**
+ * xmlRelaxNGCheckGroupAttrs:
+ * @ctxt: a Relax-NG parser context
+ * @def: the group definition
+ *
+ * Detects violations of rule 7.3
+ */
+static void
+xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def) {
+ xmlRelaxNGDefinePtr **list;
+ xmlRelaxNGDefinePtr cur;
+ int nbchild = 0, i, j, ret;
+
+ if ((def == NULL) ||
+ ((def->type != XML_RELAXNG_GROUP) &&
+ (def->type != XML_RELAXNG_ELEMENT)))
+ return;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return;
+
+ cur = def->attrs;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+ cur = def->content;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+
+ list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
+ sizeof(xmlRelaxNGDefinePtr *));
+ if (list == NULL) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Out of memory in group computation\n");
+ ctxt->nbErrors++;
+ return;
+ }
+ i = 0;
+ cur = def->attrs;
+ while (cur != NULL) {
+ list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
+ i++;
+ cur = cur->next;
+ }
+ cur = def->content;
+ while (cur != NULL) {
+ list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
+ i++;
+ cur = cur->next;
+ }
+
+ for (i = 0;i < nbchild;i++) {
+ if (list[i] == NULL)
+ continue;
+ for (j = 0;j < i;j++) {
+ if (list[j] == NULL)
+ continue;
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
+ if (ret == 0) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Attributes conflicts in group\n");
+ ctxt->nbErrors++;
+ }
+ }
+ }
+ for (i = 0;i < nbchild;i++) {
+ if (list[i] != NULL)
+ xmlFree(list[i]);
+ }
+ xmlFree(list);
+}
+
+/**
* xmlRelaxNGComputeInterleaves:
* @def: the interleave definition
* @ctxt: a Relax-NG parser context
- * @node: the data node.
+ * @name: the definition name
*
* A lot of work for preprocessing interleave definitions
* is potentially needed to get a decent execution speed at runtime
@@ -2199,7 +2294,6 @@
xmlChar *name ATTRIBUTE_UNUSED) {
xmlRelaxNGDefinePtr cur;
- xmlRelaxNGDefinePtr *list = NULL;
xmlRelaxNGPartitionPtr partitions = NULL;
xmlRelaxNGInterleaveGroupPtr *groups = NULL;
xmlRelaxNGInterleaveGroupPtr group;
@@ -2207,6 +2301,13 @@
int nbgroups = 0;
int nbchild = 0;
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return;
+
#ifdef DEBUG_INTERLEAVE
xmlGenericError(xmlGenericErrorContext,
"xmlRelaxNGComputeInterleaves(%s)\n",
@@ -2232,11 +2333,11 @@
if (groups[nbgroups] == NULL)
goto error;
groups[nbgroups]->rule = cur;
- groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur);
+ groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
+ groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
nbgroups++;
cur = cur->next;
}
- list = NULL;
#ifdef DEBUG_INTERLEAVE
xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups);
#endif
@@ -2262,12 +2363,20 @@
"Element or text conflicts in interleave\n");
ctxt->nbErrors++;
}
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
+ groups[j]->attrs);
+ if (ret == 0) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Attributes conflicts in interleave\n");
+ ctxt->nbErrors++;
+ }
}
}
partitions->groups = groups;
/*
- * Free Up the child list, and save the partition list back in the def
+ * and save the partition list back in the def
*/
def->data = partitions;
return;
@@ -2277,8 +2386,6 @@
ctxt->error(ctxt->userData,
"Out of memory in interleave computation\n");
ctxt->nbErrors++;
- if (list == NULL)
- xmlFree(list);
if (groups != NULL) {
for (i = 0;i < nbgroups;i++)
if (groups[i] != NULL) {
@@ -4077,6 +4184,10 @@
ret = (xmlRelaxNGContentType) cur->depth + 15;
}
} else if (cur->type == XML_RELAXNG_ELEMENT) {
+ /*
+ * The 7.3 Attribute derivation rule for groups is plugged there
+ */
+ xmlRelaxNGCheckGroupAttrs(ctxt, cur);
if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
@@ -4214,6 +4325,10 @@
else
nflags = flags;
ret = xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
+ /*
+ * The 7.3 Attribute derivation rule for groups is plugged there
+ */
+ xmlRelaxNGCheckGroupAttrs(ctxt, cur);
} else if (cur->type == XML_RELAXNG_INTERLEAVE) {
if (flags & XML_RELAXNG_IN_LIST) {
if (ctxt->error != NULL)
@@ -4955,6 +5070,9 @@
xmlFree(name);
}
}
+ /*
+ * 4.16
+ */
if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
if (ctxt->error != NULL)
@@ -4967,6 +5085,9 @@
(cur != root)) {
int oldflags = ctxt->flags;
+ /*
+ * 4.16
+ */
if ((cur->parent != NULL) &&
(xmlStrEqual(cur->parent->name, BAD_CAST "anyName"))) {
ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
@@ -4981,6 +5102,9 @@
goto skip_children;
}
} else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
+ /*
+ * 4.16
+ */
if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,