1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-30 22:43:14 +03:00

Fixed a bug in xmlSchemasCheckFacet, which did not create a computed value

* xmlschemas.c: Fixed a bug in xmlSchemasCheckFacet, which did
  not create a computed value on a facet and thus crashed during
  validation of instances.
  Expanded validity checks for min/maxOccurs attributes.
  Expanded validity checks for the value of the attribute "form".
This commit is contained in:
Kasimier T. Buchcik
2004-08-30 10:56:53 +00:00
parent 3ffe90ea1c
commit b4a9e64f75
2 changed files with 181 additions and 113 deletions

View File

@ -1,3 +1,11 @@
Mon Aug 30 12:45:46 CEST 2004 Kasimier Buchcik <libxml2-cvs@cazic.net>
* xmlschemas.c: Fixed a bug in xmlSchemasCheckFacet, which did
not create a computed value on a facet and thus crashed during
validation of instances.
Expanded validity checks for min/maxOccurs attributes.
Expanded validity checks for the value of the attribute "form".
Fri Aug 27 18:32:24 PST 2004 William Brack <wbrack@mmm.com.hk> Fri Aug 27 18:32:24 PST 2004 William Brack <wbrack@mmm.com.hk>
* xmlstring.c: fixed a problem with xmlCheckUTF8 reported on the * xmlstring.c: fixed a problem with xmlCheckUTF8 reported on the

View File

@ -3444,33 +3444,57 @@ xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
* Returns the default if not found, or the value * Returns the default if not found, or the value
*/ */
static int static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
int min, int max, int def, const char *expected)
{ {
const xmlChar *val, *cur; const xmlChar *val, *cur;
int ret = 0; int ret = 0;
xmlAttrPtr attr;
val = xmlSchemaGetProp(ctxt, node, "maxOccurs"); attr = xmlSchemaGetPropNode(node, "maxOccurs");
if (val == NULL) if (attr == NULL)
return (1); return (def);
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
if (xmlStrEqual(val, (const xmlChar *) "unbounded")) { if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
return (UNBOUNDED); /* encoding it with -1 might be another option */ if (max != UNBOUNDED) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
/* XML_SCHEMAP_INVALID_MINOCCURS, */
NULL, NULL, (xmlNodePtr) attr, NULL, expected,
val, NULL, NULL, NULL);
return (def);
} else
return (UNBOUNDED); /* encoding it with -1 might be another option */
} }
cur = val; cur = val;
while (IS_BLANK_CH(*cur)) while (IS_BLANK_CH(*cur))
cur++; cur++;
if (*cur == 0) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
/* XML_SCHEMAP_INVALID_MINOCCURS, */
NULL, NULL, (xmlNodePtr) attr, NULL, expected,
val, NULL, NULL, NULL);
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) { while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0'); ret = ret * 10 + (*cur - '0');
cur++; cur++;
} }
while (IS_BLANK_CH(*cur)) while (IS_BLANK_CH(*cur))
cur++; cur++;
if (*cur != 0) { /*
xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS, * TODO: Restrict the maximal value to Integer.
"The value '%s' of the attribute 'maxOccurs' is invalid.\n", */
val, NULL); if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
return (1); xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
/* XML_SCHEMAP_INVALID_MINOCCURS, */
NULL, NULL, (xmlNodePtr) attr, NULL, expected,
val, NULL, NULL, NULL);
return (def);
} }
return (ret); return (ret);
} }
@ -3485,28 +3509,44 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
* Returns the default if not found, or the value * Returns the default if not found, or the value
*/ */
static int static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
int min, int max, int def, const char *expected)
{ {
const xmlChar *val, *cur; const xmlChar *val, *cur;
int ret = 0; int ret = 0;
xmlAttrPtr attr;
val = xmlSchemaGetProp(ctxt, node, "minOccurs"); attr = xmlSchemaGetPropNode(node, "minOccurs");
if (val == NULL) if (attr == NULL)
return (1); return (def);
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
cur = val; cur = val;
while (IS_BLANK_CH(*cur)) while (IS_BLANK_CH(*cur))
cur++; cur++;
if (*cur == 0) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
/* XML_SCHEMAP_INVALID_MINOCCURS, */
NULL, NULL, (xmlNodePtr) attr, NULL, expected,
val, NULL, NULL, NULL);
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) { while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0'); ret = ret * 10 + (*cur - '0');
cur++; cur++;
} }
while (IS_BLANK_CH(*cur)) while (IS_BLANK_CH(*cur))
cur++; cur++;
if (*cur != 0) { /*
xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS, * TODO: Restrict the maximal value to Integer.
"invalid value for minOccurs: %s\n", val, NULL); */
return (1); if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
/* XML_SCHEMAP_INVALID_MINOCCURS, */
NULL, NULL, (xmlNodePtr) attr, NULL, expected,
val, NULL, NULL, NULL);
return (def);
} }
return (ret); return (ret);
} }
@ -4207,6 +4247,47 @@ xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
} }
return (ret); return (ret);
} }
static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
xmlSchemaTypePtr item,
xmlNodePtr node,
int minOccurs,
int maxOccurs) {
if (maxOccurs != UNBOUNDED) {
/*
* TODO: Maby we should better not create the particle,
* if min/max is invalid, since it could confuse the build of the
* content model.
*/
/*
* 3.9.6 Schema Component Constraint: Particle Correct
*
*/
if (maxOccurs < 1) {
/*
* 2.2 {max occurs} must be greater than or equal to 1.
*/
xmlSchemaPCustomAttrErr(ctxt,
XML_SCHEMAP_P_PROPS_CORRECT_2_2,
NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
"The value must be greater than or equal to 1");
return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
} else if (minOccurs > maxOccurs) {
/*
* 2.1 {min occurs} must not be greater than {max occurs}.
*/
xmlSchemaPCustomAttrErr(ctxt,
XML_SCHEMAP_P_PROPS_CORRECT_2_1,
NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
"The value must not be greater than the value of 'maxOccurs'");
return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
}
}
return (0);
}
/** /**
* xmlSchemaParseAny: * xmlSchemaParseAny:
* @ctxt: a schema validation context * @ctxt: a schema validation context
@ -4226,24 +4307,38 @@ xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr child = NULL; xmlNodePtr child = NULL;
xmlChar name[30]; xmlChar name[30];
xmlSchemaWildcardPtr wildc; xmlSchemaWildcardPtr wildc;
int minOccurs, maxOccurs;
if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return (NULL); return (NULL);
maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
"(nonNegativeInteger | unbounded)");
minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
"nonNegativeInteger");
if ((minOccurs == 0) && (maxOccurs == 0))
return (NULL);
snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1); snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
type = xmlSchemaAddType(ctxt, schema, name, NULL, node); type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
if (type == NULL) if (type == NULL)
return (NULL); return (NULL);
type->node = node; type->node = node;
type->type = XML_SCHEMA_TYPE_ANY; type->type = XML_SCHEMA_TYPE_ANY;
type->minOccurs = xmlGetMinOccurs(ctxt, node);
type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
wildc = xmlSchemaAddWildcard(ctxt); wildc = xmlSchemaAddWildcard(ctxt);
/* /*
* Check min/max sanity.
*/
type->maxOccurs = maxOccurs;
type->minOccurs = minOccurs;
xmlSchemaPCheckParticleCorrect_2(ctxt, type,
node, type->minOccurs, type->maxOccurs);
/*
* This is not nice, since it is won't be used as a attribute wildcard, * This is not nice, since it is won't be used as a attribute wildcard,
* but better than adding a field to the structure. * but better than adding a field to the structure.
*/ */
type->attributeWildcard = wildc; type->attributeWildcard = wildc;
xmlSchemaParseWildcardNs(ctxt, schema, wildc, node); xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
child = node->children; child = node->children;
if (IS_SCHEMA(child, "annotation")) { if (IS_SCHEMA(child, "annotation")) {
type->annot = xmlSchemaParseAnnotation(ctxt, schema, child); type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
@ -4501,25 +4596,23 @@ xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
/* /*
* Evaluate the target namespace * Evaluate the target namespace
*/ */
if (schema->targetNamespace != NULL) { if (topLevel) {
if (topLevel) { ns = schema->targetNamespace;
ns = schema->targetNamespace; } else {
} else { attr = xmlSchemaGetPropNode(node, "form");
attr = xmlSchemaGetPropNode(node, "form"); if (attr != NULL) {
if (attr != NULL) { attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { ns = schema->targetNamespace;
ns = schema->targetNamespace; } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) { xmlSchemaPSimpleTypeErr(ctxt,
xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, &repName, NULL, (xmlNodePtr) attr,
&repName, NULL, (xmlNodePtr) attr, NULL, "(qualified | unqualified)",
NULL, "(qualified | unqualified)", attrValue, NULL, NULL, NULL);
attrValue, NULL, NULL, NULL); }
} } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
} else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) ns = schema->targetNamespace;
ns = schema->targetNamespace;
}
} }
ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node); ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
if (ret == NULL) { if (ret == NULL) {
@ -4929,9 +5022,9 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* to no component at all * to no component at all
* TODO: It might be better to validate the element, even if it won't be * TODO: It might be better to validate the element, even if it won't be
* used. * used.
*/ */
minOccurs = xmlGetMinOccurs(ctxt, node); minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
maxOccurs = xmlGetMaxOccurs(ctxt, node); maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
if ((minOccurs == 0) && (maxOccurs == 0)) if ((minOccurs == 0) && (maxOccurs == 0))
return (NULL); return (NULL);
/* /*
@ -5013,26 +5106,23 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
/* /*
* Evaluate the target namespace. * Evaluate the target namespace.
*/ */
if (schema->targetNamespace != NULL) { if (topLevel) {
if (topLevel) { ns = schema->targetNamespace;
ns = schema->targetNamespace; } else {
} else { attr = xmlSchemaGetPropNode(node, "form");
attr = xmlSchemaGetPropNode(node, "form"); if (attr != NULL) {
if (attr != NULL) { attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
ns = schema->targetNamespace;
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
(xmlChar **) &xmlSchemaElemDesElemDecl, NULL,
(xmlNodePtr) attr,
NULL, "(qualified | unqualified)",
attrValue, NULL, NULL, NULL);
}
} else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
ns = schema->targetNamespace; ns = schema->targetNamespace;
} } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
&repName, NULL, (xmlNodePtr) attr,
NULL, "(qualified | unqualified)",
attrValue, NULL, NULL, NULL);
}
} else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
ns = schema->targetNamespace;
} }
ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel); ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
if (ret == NULL) { if (ret == NULL) {
@ -5183,37 +5273,9 @@ xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
ret->id = xmlSchemaGetProp(ctxt, node, "id"); ret->id = xmlSchemaGetProp(ctxt, node, "id");
ret->minOccurs = minOccurs; ret->minOccurs = minOccurs;
ret->maxOccurs = maxOccurs; ret->maxOccurs = maxOccurs;
if ((topLevel != 1) && (ret->maxOccurs != UNBOUNDED)) { if (topLevel != 1)
/* xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
* TODO: Maby we should better not create the element/particle, node, minOccurs, maxOccurs);
* if min/max is invalid, since it could confuse the build of the
* content model.
*/
/*
* 3.9.6 Schema Component Constraint: Particle Correct
*
*/
if (maxOccurs < 1) {
/*
* 2.2 {max occurs} must be greater than or equal to 1.
*/
xmlSchemaPCustomAttrErr(ctxt,
XML_SCHEMAP_P_PROPS_CORRECT_2_2,
&repName, (xmlSchemaTypePtr) ret,
xmlSchemaGetPropNode(node, "maxOccurs"),
"The value must be greater than or equal to 1");
} else if (minOccurs > maxOccurs) {
/*
* 2.1 {min occurs} must not be greater than {max occurs}.
*/
xmlSchemaPCustomAttrErr(ctxt,
XML_SCHEMAP_P_PROPS_CORRECT_2_1,
&repName, (xmlSchemaTypePtr) ret,
xmlSchemaGetPropNode(node, "minOccurs"),
"The value must not be greater than the value of 'maxOccurs'");
}
}
/* /*
* And now for the children... * And now for the children...
*/ */
@ -5676,8 +5738,11 @@ xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type->id = xmlSchemaGetProp(ctxt, node, "id"); type->id = xmlSchemaGetProp(ctxt, node, "id");
type->ref = ref; type->ref = ref;
type->refNs = refNs; type->refNs = refNs;
type->minOccurs = xmlGetMinOccurs(ctxt, node);
type->maxOccurs = xmlGetMaxOccurs(ctxt, node); type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
xmlSchemaPCheckParticleCorrect_2(ctxt, type,
node, type->minOccurs, type->maxOccurs);
child = node->children; child = node->children;
if (IS_SCHEMA(child, "annotation")) { if (IS_SCHEMA(child, "annotation")) {
@ -5739,16 +5804,9 @@ xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
type->node = node; type->node = node;
type->type = XML_SCHEMA_TYPE_ALL; type->type = XML_SCHEMA_TYPE_ALL;
type->id = xmlSchemaGetProp(ctxt, node, "id"); type->id = xmlSchemaGetProp(ctxt, node, "id");
type->minOccurs = xmlGetMinOccurs(ctxt, node);
if (type->minOccurs > 1) type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MINOCCURS, type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
"<all>: The value of the attribute \"minOccurs\" is invalid. "
"Either \"0\" or \"1\" is expected.\n", NULL, NULL);
type->maxOccurs = xmlGetMaxOccurs(ctxt, node);
if (type->maxOccurs > 1)
xmlSchemaPErr(ctxt, node, XML_SCHEMAP_INVALID_MAXOCCURS,
"<all>: The value of the attribute \"maxOccurs\" is invalid. "
"Either \"0\" or \"1\" is expected.\n", NULL, NULL);
child = node->children; child = node->children;
if (IS_SCHEMA(child, "annotation")) { if (IS_SCHEMA(child, "annotation")) {
@ -6735,8 +6793,9 @@ xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* Extract and validate attributes. * Extract and validate attributes.
*/ */
type->id = xmlSchemaGetProp(ctxt, node, "id"); type->id = xmlSchemaGetProp(ctxt, node, "id");
type->minOccurs = xmlGetMinOccurs(ctxt, node); type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
type->maxOccurs = xmlGetMaxOccurs(ctxt, node); type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
"(nonNegativeInteger | unbounded)");
/* /*
* And now for the children... * And now for the children...
*/ */
@ -6842,8 +6901,9 @@ xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
* Extract and validate attributes. * Extract and validate attributes.
*/ */
type->id = xmlSchemaGetProp(ctxt, node, "id"); type->id = xmlSchemaGetProp(ctxt, node, "id");
type->minOccurs = xmlGetMinOccurs(ctxt, node); type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
type->maxOccurs = xmlGetMaxOccurs(ctxt, node); type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
"(nonNegativeInteger | unbounded)");
/* /*
* And now for the children... * And now for the children...
*/ */
@ -11380,7 +11440,7 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
xmlSchemaTypePtr typeDecl, xmlSchemaTypePtr typeDecl,
xmlSchemaParserCtxtPtr ctxt, const xmlChar * name) xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
{ {
static xmlSchemaTypePtr nonNegativeIntegerType = NULL; xmlSchemaTypePtr nonNegativeIntegerType = NULL;
int ret = 0; int ret = 0;
if (nonNegativeIntegerType == NULL) { if (nonNegativeIntegerType == NULL) {
@ -11494,7 +11554,7 @@ xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
tmp = tmp =
xmlSchemaValidatePredefinedType(nonNegativeIntegerType, xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
facet->value, facet->value,
&facet->val); &(facet->val));
if (tmp != 0) { if (tmp != 0) {
/* error code */ /* error code */
if (ctxt != NULL) { if (ctxt != NULL) {