Skip to content

Commit 9292977

Browse files
committed
parser: Fix detection of duplicate attributes
We really need a second scan if more than one namespace clash was detected.
1 parent 5a2a243 commit 9292977

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

parser.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8912,6 +8912,35 @@ xmlAttrHashInsert(xmlParserCtxtPtr ctxt, unsigned size, const xmlChar *name,
89128912
return(INT_MAX);
89138913
}
89148914

8915+
static int
8916+
xmlAttrHashInsertQName(xmlParserCtxtPtr ctxt, unsigned size,
8917+
const xmlChar *name, const xmlChar *prefix,
8918+
unsigned hashValue, int aindex) {
8919+
xmlAttrHashBucket *table = ctxt->attrHash;
8920+
xmlAttrHashBucket *bucket;
8921+
unsigned hindex;
8922+
8923+
hindex = hashValue & (size - 1);
8924+
bucket = &table[hindex];
8925+
8926+
while (bucket->index >= 0) {
8927+
const xmlChar **atts = &ctxt->atts[bucket->index];
8928+
8929+
if ((name == atts[0]) && (prefix == atts[1]))
8930+
return(bucket->index);
8931+
8932+
hindex++;
8933+
bucket++;
8934+
if (hindex >= size) {
8935+
hindex = 0;
8936+
bucket = table;
8937+
}
8938+
}
8939+
8940+
bucket->index = aindex;
8941+
8942+
return(INT_MAX);
8943+
}
89158944
/**
89168945
* xmlParseStartTag2:
89178946
* @ctxt: an XML parser context
@@ -8960,6 +8989,8 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
89608989
int nratts, nbatts, nbdef;
89618990
int i, j, nbNs, nbTotalDef, attval, nsIndex, maxAtts;
89628991
int alloc = 0;
8992+
int numNsErr = 0;
8993+
int numDupErr = 0;
89638994

89648995
if (RAW != '<') return(NULL);
89658996
NEXT1;
@@ -9338,10 +9369,12 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
93389369
if (res < INT_MAX) {
93399370
if (aprefix == atts[res+1]) {
93409371
xmlErrAttributeDup(ctxt, aprefix, attname);
9372+
numDupErr += 1;
93419373
} else {
93429374
xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
93439375
"Namespaced Attribute %s in '%s' redefined\n",
93449376
attname, nsuri, NULL);
9377+
numNsErr += 1;
93459378
}
93469379
}
93479380
}
@@ -9440,6 +9473,43 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
94409473
}
94419474
}
94429475

9476+
/*
9477+
* Using a single hash table for nsUri/localName pairs cannot
9478+
* detect duplicate QNames reliably. The following example will
9479+
* only result in two namespace errors.
9480+
*
9481+
* <doc xmlns:a="a" xmlns:b="a">
9482+
* <elem a:a="" b:a="" b:a=""/>
9483+
* </doc>
9484+
*
9485+
* If we saw more than one namespace error but no duplicate QNames
9486+
* were found, we have to scan for duplicate QNames.
9487+
*/
9488+
if ((numDupErr == 0) && (numNsErr > 1)) {
9489+
memset(ctxt->attrHash, -1,
9490+
attrHashSize * sizeof(ctxt->attrHash[0]));
9491+
9492+
for (i = 0, j = 0; j < nratts; i += 5, j++) {
9493+
unsigned hashValue, nameHashValue, prefixHashValue;
9494+
int res;
9495+
9496+
aprefix = atts[i+1];
9497+
if (aprefix == NULL)
9498+
continue;
9499+
9500+
attname = atts[i];
9501+
/* Hash values always have bit 31 set, see dict.c */
9502+
nameHashValue = ctxt->attallocs[j] | 0x80000000;
9503+
prefixHashValue = xmlDictComputeHash(ctxt->dict, aprefix);
9504+
9505+
hashValue = xmlDictCombineHash(nameHashValue, prefixHashValue);
9506+
res = xmlAttrHashInsertQName(ctxt, attrHashSize, attname,
9507+
aprefix, hashValue, i);
9508+
if (res < INT_MAX)
9509+
xmlErrAttributeDup(ctxt, aprefix, attname);
9510+
}
9511+
}
9512+
94439513
/*
94449514
* Reconstruct attribute pointers
94459515
*/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
2+
<elem a:a="" b:a="" b:a=""/>
3+
^
4+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
5+
<elem a:a="" b:a="" b:a=""/>
6+
^
7+
./test/errors/dup-xml-attr2.xml:2: parser error : Attribute b:a redefined
8+
<elem a:a="" b:a="" b:a=""/>
9+
^
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
2+
<elem a:a="" b:a="" b:a=""/>
3+
^
4+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
5+
<elem a:a="" b:a="" b:a=""/>
6+
^
7+
./test/errors/dup-xml-attr2.xml:2: parser error : Attribute b:a redefined
8+
<elem a:a="" b:a="" b:a=""/>
9+
^
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
2+
<elem a:a="" b:a="" b:a=""/>
3+
^
4+
./test/errors/dup-xml-attr2.xml:2: namespace error : Namespaced Attribute a in 'urn:a' redefined
5+
<elem a:a="" b:a="" b:a=""/>
6+
^
7+
./test/errors/dup-xml-attr2.xml:2: parser error : Attribute b:a redefined
8+
<elem a:a="" b:a="" b:a=""/>
9+
^
10+
./test/errors/dup-xml-attr2.xml : failed to parse

test/errors/dup-xml-attr2.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<doc xmlns:a="urn:a" xmlns:b="urn:a">
2+
<elem a:a="" b:a="" b:a=""/>
3+
</doc>

0 commit comments

Comments
 (0)