Apply patch NSAttFix3.diff for bug #692964 (with one minor modification).

This also fixes bug #695401.
This commit is contained in:
Karl Waclawek 2003-03-07 15:54:08 +00:00
parent 2d3510fa5f
commit 8650b04b24
2 changed files with 119 additions and 74 deletions

View file

@ -104,7 +104,8 @@ enum XML_Error {
XML_ERROR_UNEXPECTED_STATE,
XML_ERROR_ENTITY_DECLARED_IN_PE,
XML_ERROR_FEATURE_REQUIRES_XML_DTD,
XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING
XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
XML_ERROR_UNBOUND_PREFIX
};
enum XML_Content_Type {

View file

@ -223,6 +223,11 @@ typedef struct {
const XML_Char *value;
} DEFAULT_ATTRIBUTE;
typedef struct {
unsigned long hash;
const XML_Char *uriName;
} NS_ATT;
typedef struct {
const XML_Char *name;
PREFIX *prefix;
@ -499,6 +504,8 @@ struct XML_ParserStruct {
int m_nSpecifiedAtts;
int m_idAttIndex;
ATTRIBUTE *m_atts;
NS_ATT *m_nsAtts;
int m_nsAttsSize;
POSITION m_position;
STRING_POOL m_tempPool;
STRING_POOL m_temp2Pool;
@ -601,6 +608,8 @@ struct XML_ParserStruct {
#define attsSize (parser->m_attsSize)
#define nSpecifiedAtts (parser->m_nSpecifiedAtts)
#define idAttIndex (parser->m_idAttIndex)
#define nsAtts (parser->m_nsAtts)
#define nsAttsSize (parser->m_nsAttsSize)
#define tempPool (parser->m_tempPool)
#define temp2Pool (parser->m_temp2Pool)
#define groupConnector (parser->m_groupConnector)
@ -747,6 +756,9 @@ parserCreate(const XML_Char *encodingName,
ns = XML_FALSE;
ns_triplets = XML_FALSE;
nsAtts = NULL;
nsAttsSize = 0;
poolInit(&tempPool, &(parser->m_mem));
poolInit(&temp2Pool, &(parser->m_mem));
parserInit(parser, encodingName);
@ -868,8 +880,7 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
freeTagList = tag;
}
moveToFreeBindingList(parser, inheritedBindings);
if (unknownEncodingMem)
FREE(unknownEncodingMem);
FREE(unknownEncodingMem);
if (unknownEncodingRelease)
unknownEncodingRelease(unknownEncodingData);
poolClear(&tempPool);
@ -1072,13 +1083,11 @@ XML_ParserFree(XML_Parser parser)
#endif /* XML_DTD */
dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
FREE((void *)atts);
if (groupConnector)
FREE(groupConnector);
if (buffer)
FREE(buffer);
FREE(groupConnector);
FREE(buffer);
FREE(dataBuf);
if (unknownEncodingMem)
FREE(unknownEncodingMem);
FREE(nsAtts);
FREE(unknownEncodingMem);
if (unknownEncodingRelease)
unknownEncodingRelease(unknownEncodingData);
FREE(parser);
@ -1660,7 +1669,8 @@ XML_ErrorString(enum XML_Error code)
XML_L("unexpected parser state - please send a bug report"),
XML_L("entity declared in parameter entity"),
XML_L("requested feature requires XML_DTD support in Expat"),
XML_L("cannot change setting once parsing has begun")
XML_L("cannot change setting once parsing has begun"),
XML_L("unbound prefix")
};
if (code > 0 && code < sizeof(message)/sizeof(message[0]))
return message[code];
@ -2409,7 +2419,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
+ XmlNameLength(enc, atts[i].name));
if (!attId)
return XML_ERROR_NO_MEMORY;
/* detect duplicate attributes */
/* detect duplicate attributes by their QNames */
if ((attId->name)[-1]) {
if (enc == encoding)
eventPtr = atts[i].name;
@ -2509,48 +2519,88 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
}
appAtts[attIndex] = 0;
/* expand prefixed attribute names and
clear flags that say whether attributes were specified */
i = 0;
if (nPrefixes) {
/* expand prefixed attribute names */
int j;
if ((nPrefixes * 2) > nsAttsSize) {
NS_ATT *temp = (NS_ATT *)REALLOC(nsAtts, nPrefixes * 2 * sizeof(NS_ATT));
if (!temp)
return XML_ERROR_NO_MEMORY;
nsAtts = temp;
nsAttsSize = nPrefixes * 2;
}
/* clear nsAtts hash table */
for (j = 0; j < nsAttsSize; j++)
nsAtts[j].uriName = NULL;
for (; i < attIndex; i += 2) {
if (appAtts[i][-1] == 2) {
const XML_Char *s = appAtts[i];
if (s[-1] == 2) {
ATTRIBUTE_ID *id;
((XML_Char *)(appAtts[i]))[-1] = 0;
id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, appAtts[i], 0);
if (id->prefix->binding) {
int j;
const BINDING *b = id->prefix->binding;
const XML_Char *s = appAtts[i];
for (j = 0; j < b->uriLen; j++) {
if (!poolAppendChar(&tempPool, b->uri[j]))
return XML_ERROR_NO_MEMORY;
const BINDING *b;
unsigned long uriHash = 0;
((XML_Char *)s)[-1] = 0;
id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
b = id->prefix->binding;
if (!b)
return XML_ERROR_UNBOUND_PREFIX;
/* b->uri includes namespace separator */
for (j = 0; j < b->uriLen; j++) {
const XML_Char c = b->uri[j];
if (!poolAppendChar(&tempPool, c))
return XML_ERROR_NO_MEMORY;
uriHash = (uriHash << 5) + uriHash + (unsigned char)c;
}
while (*s++ != XML_T(':'))
;
do {
const XML_Char c = *s;
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
uriHash = (uriHash << 5) + uriHash + (unsigned char)c;
} while (*s++);
/* detect duplicate attributes based on uriName = uri + local name */
for (j = uriHash & (nsAttsSize - 1);
nsAtts[j].uriName;
j == 0 ? j = nsAttsSize - 1 : --j) {
if (uriHash == nsAtts[j].hash) {
const XML_Char *s1 = poolStart(&tempPool); /* null-terminated */
const XML_Char *s2 = nsAtts[j].uriName;
for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
if (*s1 == 0)
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
while (*s++ != XML_T(':'))
;
}
if (ns_triplets) {
tempPool.ptr[-1] = namespaceSeparator;
s = b->prefix->name;
do {
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
} while (*s++);
if (ns_triplets) {
tempPool.ptr[-1] = namespaceSeparator;
s = b->prefix->name;
do {
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
} while (*s++);
}
appAtts[i] = poolStart(&tempPool);
poolFinish(&tempPool);
}
s = poolStart(&tempPool);
appAtts[i] = s;
poolFinish(&tempPool);
/* fill empty slot with new attribute */
nsAtts[j].hash = uriHash;
nsAtts[j].uriName = s;
if (!--nPrefixes)
break;
}
else
((XML_Char *)(appAtts[i]))[-1] = 0;
((XML_Char *)s)[-1] = 0;
}
}
/* clear the flags that say whether attributes were specified */
/* clear flags for the remaining attributes */
for (; i < attIndex; i += 2)
((XML_Char *)(appAtts[i]))[-1] = 0;
for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
@ -2560,7 +2610,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
if (elementType->prefix) {
binding = elementType->prefix->binding;
if (!binding)
return XML_ERROR_NONE;
return XML_ERROR_UNBOUND_PREFIX;
localPart = tagNamePtr->str;
while (*localPart++ != XML_T(':'))
;
@ -2599,8 +2649,9 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
uri = binding->uri + binding->uriLen;
memcpy(uri, localPart, i * sizeof(XML_Char));
if (prefixLen) {
uri = uri + (i - 1);
if (namespaceSeparator) { *(uri) = namespaceSeparator; }
uri = uri + (i - 1);
if (namespaceSeparator)
*uri = namespaceSeparator;
memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
}
tagNamePtr->str = binding->uri;
@ -2655,6 +2706,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
b->prefix = prefix;
b->attId = attId;
b->prevPrefixBinding = prefix->binding;
/* NULL binding when default namespace undeclared */
if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
prefix->binding = NULL;
else
@ -3502,8 +3554,8 @@ doProlog(XML_Parser parser,
case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
if (!defineAttribute(declElementType, declAttributeId,
declAttributeIsCdata, declAttributeIsId, 0,
parser))
declAttributeIsCdata, declAttributeIsId,
0, parser))
return XML_ERROR_NO_MEMORY;
if (attlistDeclHandler && declAttributeType) {
if (*declAttributeType == XML_T('(')
@ -3529,11 +3581,11 @@ doProlog(XML_Parser parser,
case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
const XML_Char *attVal;
enum XML_Error result
= storeAttributeValue(parser, enc, declAttributeIsCdata,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar,
&dtd->pool);
enum XML_Error result =
storeAttributeValue(parser, enc, declAttributeIsCdata,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar,
&dtd->pool);
if (result)
return result;
attVal = poolStart(&dtd->pool);
@ -4749,6 +4801,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
name = poolStoreString(&dtd->pool, enc, start, end);
if (!name)
return NULL;
/* skip quotation mark - its storage will be re-used (like in name[-1]) */
++name;
id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
if (!id)
@ -4774,6 +4827,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
else {
int i;
for (i = 0; name[i]; i++) {
/* attributes without prefix are *not* in the default namespace */
if (name[i] == XML_T(':')) {
int j;
for (j = 0; j < i; j++) {
@ -5013,14 +5067,12 @@ dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
p->defaultPrefix.binding = NULL;
p->in_eldecl = XML_FALSE;
if (p->scaffIndex) {
ms->free_fcn(p->scaffIndex);
p->scaffIndex = NULL;
}
if (p->scaffold) {
ms->free_fcn(p->scaffold);
p->scaffold = NULL;
}
ms->free_fcn(p->scaffIndex);
p->scaffIndex = NULL;
ms->free_fcn(p->scaffold);
p->scaffold = NULL;
p->scaffLevel = 0;
p->scaffSize = 0;
p->scaffCount = 0;
@ -5055,10 +5107,8 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
poolDestroy(&(p->entityValuePool));
#endif /* XML_DTD */
if (isDocEntity) {
if (p->scaffIndex)
ms->free_fcn(p->scaffIndex);
if (p->scaffold)
ms->free_fcn(p->scaffold);
ms->free_fcn(p->scaffIndex);
ms->free_fcn(p->scaffold);
}
ms->free_fcn(p);
}
@ -5264,13 +5314,13 @@ copyEntityTable(HASH_TABLE *newTable,
#define INIT_SIZE 64
static int FASTCALL
static XML_Bool FASTCALL
keyeq(KEY s1, KEY s2)
{
for (; *s1 == *s2; s1++, s2++)
if (*s1 == 0)
return 1;
return 0;
return XML_TRUE;
return XML_FALSE;
}
static unsigned long FASTCALL
@ -5351,11 +5401,8 @@ hashTableClear(HASH_TABLE *table)
{
size_t i;
for (i = 0; i < table->size; i++) {
NAMED *p = table->v[i];
if (p) {
table->mem->free_fcn(p);
table->v[i] = NULL;
}
table->mem->free_fcn(table->v[i]);
table->v[i] = NULL;
}
table->usedLim = table->size / 2;
table->used = 0;
@ -5365,13 +5412,9 @@ static void FASTCALL
hashTableDestroy(HASH_TABLE *table)
{
size_t i;
for (i = 0; i < table->size; i++) {
NAMED *p = table->v[i];
if (p)
table->mem->free_fcn(p);
}
if (table->v)
table->mem->free_fcn(table->v);
for (i = 0; i < table->size; i++)
table->mem->free_fcn(table->v[i]);
table->mem->free_fcn(table->v);
}
static void FASTCALL
@ -5709,3 +5752,4 @@ getElementType(XML_Parser parser,
}
return ret;
}