mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00
579746 XSD validation not correct / nilable groups
* xmlschemas.c: when a particle need to be processed via counted transition, if the group is nillable, the counting won't work, so keep track of nillable subset as they are built and generate the appropriate epsilon transitions as needed * test/schemas/579746* result/schemas/579746*: add related test cases based on the bug report
This commit is contained in:
parent
74eaec1496
commit
4013e83e84
1
result/schemas/579746_0_0
Normal file
1
result/schemas/579746_0_0
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_0.xml validates
|
0
result/schemas/579746_0_0.err
Normal file
0
result/schemas/579746_0_0.err
Normal file
1
result/schemas/579746_0_1
Normal file
1
result/schemas/579746_0_1
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_1.xml validates
|
0
result/schemas/579746_0_1.err
Normal file
0
result/schemas/579746_0_1.err
Normal file
1
result/schemas/579746_0_2
Normal file
1
result/schemas/579746_0_2
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_2.xml validates
|
0
result/schemas/579746_0_2.err
Normal file
0
result/schemas/579746_0_2.err
Normal file
1
result/schemas/579746_0_3
Normal file
1
result/schemas/579746_0_3
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml fails to validate
|
1
result/schemas/579746_0_3.err
Normal file
1
result/schemas/579746_0_3.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml:5: element customer: Schemas validity error : Element 'customer': This element is not expected.
|
1
result/schemas/579746_0_4
Normal file
1
result/schemas/579746_0_4
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_4.xml validates
|
0
result/schemas/579746_0_4.err
Normal file
0
result/schemas/579746_0_4.err
Normal file
1
result/schemas/579746_0_5
Normal file
1
result/schemas/579746_0_5
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml fails to validate
|
1
result/schemas/579746_0_5.err
Normal file
1
result/schemas/579746_0_5.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml:5: element comment: Schemas validity error : Element 'comment': This element is not expected.
|
1
result/schemas/579746_1_0
Normal file
1
result/schemas/579746_1_0
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_0.xml validates
|
0
result/schemas/579746_1_0.err
Normal file
0
result/schemas/579746_1_0.err
Normal file
1
result/schemas/579746_1_1
Normal file
1
result/schemas/579746_1_1
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_1.xml validates
|
0
result/schemas/579746_1_1.err
Normal file
0
result/schemas/579746_1_1.err
Normal file
1
result/schemas/579746_1_2
Normal file
1
result/schemas/579746_1_2
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_2.xml validates
|
0
result/schemas/579746_1_2.err
Normal file
0
result/schemas/579746_1_2.err
Normal file
1
result/schemas/579746_1_3
Normal file
1
result/schemas/579746_1_3
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml fails to validate
|
1
result/schemas/579746_1_3.err
Normal file
1
result/schemas/579746_1_3.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml:5: element customer: Schemas validity error : Element 'customer': This element is not expected.
|
1
result/schemas/579746_1_4
Normal file
1
result/schemas/579746_1_4
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_4.xml validates
|
0
result/schemas/579746_1_4.err
Normal file
0
result/schemas/579746_1_4.err
Normal file
1
result/schemas/579746_1_5
Normal file
1
result/schemas/579746_1_5
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml fails to validate
|
1
result/schemas/579746_1_5.err
Normal file
1
result/schemas/579746_1_5.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml:5: element comment: Schemas validity error : Element 'comment': This element is not expected.
|
3
test/schemas/579746_0.xml
Normal file
3
test/schemas/579746_0.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
</contact>
|
11
test/schemas/579746_0.xsd
Normal file
11
test/schemas/579746_0.xsd
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:element name= "contact" type="ContactType"/>
|
||||
<xsd:complexType name="ContactType">
|
||||
<xsd:choice minOccurs="2" maxOccurs="2">
|
||||
<xsd:element name="customer" type="xsd:string" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
|
4
test/schemas/579746_1.xml
Normal file
4
test/schemas/579746_1.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
</contact>
|
10
test/schemas/579746_1.xsd
Normal file
10
test/schemas/579746_1.xsd
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:element name= "contact" type="ContactType"/>
|
||||
<xsd:complexType name="ContactType">
|
||||
<xsd:choice minOccurs="1" maxOccurs="2">
|
||||
<xsd:element name="customer" type="xsd:string" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
5
test/schemas/579746_2.xml
Normal file
5
test/schemas/579746_2.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<customer/>
|
||||
</contact>
|
7
test/schemas/579746_3.xml
Normal file
7
test/schemas/579746_3.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<comment/>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
5
test/schemas/579746_4.xml
Normal file
5
test/schemas/579746_4.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
6
test/schemas/579746_5.xml
Normal file
6
test/schemas/579746_5.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<comment/>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
95
xmlschemas.c
95
xmlschemas.c
@ -12525,7 +12525,12 @@ xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static void
|
||||
/**
|
||||
* xmlSchemaBuildContentModelForSubstGroup:
|
||||
*
|
||||
* Returns 1 if nillable, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
|
||||
{
|
||||
@ -12533,6 +12538,7 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaElementPtr elemDecl, member;
|
||||
xmlSchemaSubstGroupPtr substGroup;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
elemDecl = (xmlSchemaElementPtr) particle->children;
|
||||
/*
|
||||
@ -12548,7 +12554,7 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
"Internal error: xmlSchemaBuildContentModelForSubstGroup, "
|
||||
"declaration is marked having a subst. group but none "
|
||||
"available.\n", elemDecl->name, NULL);
|
||||
return;
|
||||
return(0);
|
||||
}
|
||||
if (counter >= 0) {
|
||||
/*
|
||||
@ -12628,21 +12634,31 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
|
||||
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
|
||||
}
|
||||
if (particle->minOccurs == 0)
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
/**
|
||||
* xmlSchemaBuildContentModelForElement:
|
||||
*
|
||||
* Returns 1 if nillable, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
xmlSchemaParticlePtr particle)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (((xmlSchemaElementPtr) particle->children)->flags &
|
||||
XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
|
||||
/*
|
||||
* Substitution groups.
|
||||
*/
|
||||
xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
|
||||
ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
|
||||
} else {
|
||||
xmlSchemaElementPtr elemDecl;
|
||||
xmlAutomataStatePtr start;
|
||||
@ -12650,7 +12666,7 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
elemDecl = (xmlSchemaElementPtr) particle->children;
|
||||
|
||||
if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
|
||||
return;
|
||||
return(0);
|
||||
if (particle->maxOccurs == 1) {
|
||||
start = ctxt->state;
|
||||
ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
|
||||
@ -12678,10 +12694,13 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
|
||||
NULL, counter);
|
||||
}
|
||||
if (particle->minOccurs == 0)
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaBuildAContentModel:
|
||||
@ -12691,21 +12710,24 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
*
|
||||
* Create the automaton for the {content type} of a complex type.
|
||||
*
|
||||
* Returns 1 if the content is nillable, 0 otherwise
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaParticlePtr particle)
|
||||
{
|
||||
int ret = 0, tmp2;
|
||||
|
||||
if (particle == NULL) {
|
||||
PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
|
||||
return;
|
||||
return(1);
|
||||
}
|
||||
if (particle->children == NULL) {
|
||||
/*
|
||||
* Just return in this case. A missing "term" of the particle
|
||||
* might arise due to an invalid "term" component.
|
||||
*/
|
||||
return;
|
||||
return(1);
|
||||
}
|
||||
|
||||
switch (particle->children->type) {
|
||||
@ -12757,7 +12779,8 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
int counter;
|
||||
xmlAutomataStatePtr hop;
|
||||
int maxOccurs =
|
||||
particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
|
||||
particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
|
||||
particle->maxOccurs - 1;
|
||||
int minOccurs =
|
||||
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
|
||||
|
||||
@ -12792,25 +12815,29 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_ELEMENT:
|
||||
xmlSchemaBuildContentModelForElement(pctxt, particle);
|
||||
ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
|
||||
break;
|
||||
case XML_SCHEMA_TYPE_SEQUENCE:{
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
|
||||
ret = 1;
|
||||
/*
|
||||
* If max and min occurances are default (1) then
|
||||
* simply iterate over the particles of the <sequence>.
|
||||
*/
|
||||
if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
|
||||
sub = particle->children->children;
|
||||
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
} else {
|
||||
@ -12830,8 +12857,9 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
tmp = pctxt->state;
|
||||
@ -12840,6 +12868,9 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
pctxt->state =
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp,
|
||||
NULL, counter);
|
||||
if (ret == 1)
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
|
||||
} else {
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
@ -12848,8 +12879,9 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
|
||||
@ -12864,6 +12896,7 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
} else if ((particle->maxOccurs > 1)
|
||||
@ -12881,8 +12914,9 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
tmp = pctxt->state;
|
||||
@ -12891,20 +12925,23 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
pctxt->state =
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
|
||||
counter);
|
||||
if (particle->minOccurs == 0) {
|
||||
if ((particle->minOccurs == 0) || (ret == 1)) {
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, oldstate,
|
||||
pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12914,6 +12951,7 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
xmlAutomataStatePtr start, end;
|
||||
|
||||
ret = 0;
|
||||
start = pctxt->state;
|
||||
end = xmlAutomataNewState(pctxt->am);
|
||||
|
||||
@ -12925,8 +12963,9 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = start;
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 == 1) ret = 1;
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
|
||||
sub = sub->next;
|
||||
}
|
||||
@ -12950,17 +12989,21 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = base;
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 == 1) ret = 1;
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
|
||||
sub = sub->next;
|
||||
}
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, base);
|
||||
xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
|
||||
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
|
||||
if (ret == 1)
|
||||
xmlAutomataNewEpsilon(pctxt->am, base, end);
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
break;
|
||||
@ -12970,9 +13013,14 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaParticlePtr sub;
|
||||
xmlSchemaElementPtr elemDecl;
|
||||
|
||||
ret = 1;
|
||||
|
||||
sub = (xmlSchemaParticlePtr) particle->children->children;
|
||||
if (sub == NULL)
|
||||
break;
|
||||
|
||||
ret = 0;
|
||||
|
||||
start = pctxt->state;
|
||||
tmp = xmlAutomataNewState(pctxt->am);
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
|
||||
@ -12984,7 +13032,7 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
if (elemDecl == NULL) {
|
||||
PERROR_INT("xmlSchemaBuildAContentModel",
|
||||
"<element> particle has no term");
|
||||
return;
|
||||
return(ret);
|
||||
};
|
||||
/*
|
||||
* NOTE: The {max occurs} of all the particles in the
|
||||
@ -13030,6 +13078,7 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -13041,14 +13090,16 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
* TODO: But the group should be substituted and not occur at
|
||||
* all in the content model at this point. Fix this.
|
||||
*/
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
xmlSchemaInternalErr2(ACTXT_CAST pctxt,
|
||||
"xmlSchemaBuildAContentModel",
|
||||
"found unexpected term of type '%s' in content model",
|
||||
WXS_ITEM_TYPE_NAME(particle->children), NULL);
|
||||
return;
|
||||
return(ret);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user