cpython: a8b164ab98bf (original) (raw)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,11 @@ Core and Builtins Library ------- +- Issue #14234: CVE-2012-0876: Randomize hashes of xml attributes in the hash
- table internal to the pyexpat module's copy of the expat library to avoid a
- denial of service due to hash collisions. Patch by David Malcolm with some
- modifications by the expat project. +
- Issue #14200: Idle shell crash on printing non-BMP unicode character.
- Issue #12818: format address no longer needlessly \ escapes ()s in names when
--- a/Modules/expat/expat.h +++ b/Modules/expat/expat.h @@ -883,6 +883,15 @@ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); +/* Sets the hash salt to use for internal hash calculations.
- Helps in preventing DoS attacks based on predicting hash
- function behavior. This must be called before parsing is started.
- Returns 1 if successful, 0 when called after parsing has started. +*/ +XMLPARSEAPI(int) +XML_SetHashSalt(XML_Parser parser,
unsigned long hash_salt);[](#l2.14)
+ /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then XML_GetErrorCode returns information about the error. */
--- a/Modules/expat/pyexpatns.h +++ b/Modules/expat/pyexpatns.h @@ -97,6 +97,7 @@ #define XML_SetEntityDeclHandler PyExpat_XML_SetEntityDeclHandler #define XML_SetExternalEntityRefHandler PyExpat_XML_SetExternalEntityRefHandler #define XML_SetExternalEntityRefHandlerArg PyExpat_XML_SetExternalEntityRefHandlerArg +#define XML_SetHashSalt PyExpat_XML_SetHashSalt #define XML_SetNamespaceDeclHandler PyExpat_XML_SetNamespaceDeclHandler #define XML_SetNotationDeclHandler PyExpat_XML_SetNotationDeclHandler #define XML_SetNotStandaloneHandler PyExpat_XML_SetNotStandaloneHandler
--- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -17,6 +17,8 @@ #include <stddef.h> #include <string.h> /* memset(), memcpy() / #include <assert.h> +#include <limits.h> / UINT_MAX / +#include <time.h> / time() */ #include "expat.h" @@ -387,12 +389,13 @@ static void dtdReset(DTD *p, const XML_M static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); static int -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); +dtdCopy(XML_Parser oldParser,
DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);[](#l4.18)
static int -copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *); - +copyEntityTable(XML_Parser oldParser,
HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);[](#l4.23)
static NAMED * -lookup(HASH_TABLE *table, KEY name, size_t createSize); +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); static void FASTCALL hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms); static void FASTCALL hashTableClear(HASH_TABLE *); @@ -425,6 +428,9 @@ static ELEMENT_TYPE * getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end); +static unsigned long generate_hash_secret_salt(void); +static XML_Bool startParsing(XML_Parser parser); + static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, @@ -542,6 +548,7 @@ struct XML_ParserStruct { XML_Bool m_useForeignDTD; enum XML_ParamEntityParsing m_paramEntityParsing; #endif
#define MALLOC(s) (parser->m_mem.malloc_fcn((s))) @@ -649,6 +656,7 @@ struct XML_ParserStruct { #define useForeignDTD (parser->m_useForeignDTD) #define paramEntityParsing (parser->m_paramEntityParsing) #endif /* XML_DTD */ +#define hash_secret_salt (parser->m_hash_secret_salt) XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName) @@ -671,22 +679,36 @@ static const XML_Char implicitContext[] 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\0' }; -XML_Parser XMLCALL -XML_ParserCreate_MM(const XML_Char *encodingName,
const XML_Memory_Handling_Suite *memsuite,[](#l4.62)
const XML_Char *nameSep)[](#l4.63)
+static unsigned long +generate_hash_secret_salt(void) {
- XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
- if (parser != NULL && ns) {
- unsigned int seed = time(NULL) % UINT_MAX;
- srand(seed);
- return rand(); +} + +static XML_Bool /* only valid for root parser */ +startParsing(XML_Parser parser) +{
- /* hash functions must be initialized before setContext() is called */ +
- if (hash_secret_salt == 0)
- hash_secret_salt = generate_hash_secret_salt();
- if (ns) { /* implicit context only set for root parser, since child parsers (i.e. external entity parsers) will inherit it */
- if (!setContext(parser, implicitContext)) {
XML_ParserFree(parser);[](#l4.86)
return NULL;[](#l4.87)
- }
- return XML_TRUE; +} + +XML_Parser XMLCALL +XML_ParserCreate_MM(const XML_Char *encodingName,
- const XML_Memory_Handling_Suite *memsuite,
- const XML_Char *nameSep)
- return parserCreate(encodingName, memsuite, nameSep, NULL); } static XML_Parser @@ -860,6 +882,7 @@ parserInit(XML_Parser parser, const XML_ useForeignDTD = XML_FALSE; paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
- hash_secret_salt = 0; } /* moves list of bindings to freeBindingList */ @@ -907,7 +930,7 @@ XML_ParserReset(XML_Parser parser, const poolClear(&temp2Pool); parserInit(parser, encodingName); dtdReset(_dtd, &parser->m_mem);
- return XML_TRUE; } enum XML_Status XMLCALL @@ -976,6 +999,12 @@ XML_ExternalEntityParserCreate(XML_Parse int oldInEntityValue = prologState.inEntityValue;
#endif XML_Bool oldns_triplets = ns_triplets;
- /* Note that the new parser shares the same hash secret as the old
parser, so that dtdCopy and copyEntityTable can lookup values[](#l4.126)
from hash tables associated with either parser without us having[](#l4.127)
to worry which hash secrets each table has.[](#l4.128)
- */
- unsigned long oldhash_secret_salt = hash_secret_salt;
#ifdef XML_DTD if (!context) @@ -1029,13 +1058,14 @@ XML_ExternalEntityParserCreate(XML_Parse externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; defaultExpandInternalEntities = oldDefaultExpandInternalEntities; ns_triplets = oldns_triplets;
#ifdef XML_DTD paramEntityParsing = oldParamEntityParsing; prologState.inEntityValue = oldInEntityValue; if (context) { #endif /* XML_DTD */
- if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem) || !setContext(parser, context)) { XML_ParserFree(parser); return NULL; @@ -1420,6 +1450,17 @@ XML_SetParamEntityParsing(XML_Parser par
#endif } +int XMLCALL +XML_SetHashSalt(XML_Parser parser,
unsigned long hash_salt)[](#l4.156)
- /* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
- return 0;
- hash_secret_salt = hash_salt;
- return 1; +} + enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { @@ -1430,6 +1471,11 @@ XML_Parse(XML_Parser parser, const char case XML_FINISHED: errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR;
- case XML_INITIALIZED:
- if (parentParser == NULL && !startParsing(parser)) {
errorCode = XML_ERROR_NO_MEMORY;[](#l4.174)
return XML_STATUS_ERROR;[](#l4.175)
- }
default: ps_parsing = XML_PARSING; } @@ -1488,11 +1534,13 @@ XML_Parse(XML_Parser parser, const char break; case XML_INITIALIZED: case XML_PARSING:
result = XML_STATUS_OK;[](#l4.184) if (isFinal) {[](#l4.185) ps_parsing = XML_FINISHED;[](#l4.186)
return result;[](#l4.187)
return XML_STATUS_OK;[](#l4.188) }[](#l4.189)
/* fall through */[](#l4.190)
default:[](#l4.191)
} @@ -1553,6 +1601,11 @@ XML_ParseBuffer(XML_Parser parser, int l case XML_FINISHED: errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR;result = XML_STATUS_OK;[](#l4.192) }[](#l4.193)
- case XML_INITIALIZED:
- if (parentParser == NULL && !startParsing(parser)) {
errorCode = XML_ERROR_NO_MEMORY;[](#l4.202)
return XML_STATUS_ERROR;[](#l4.203)
- }
default: ps_parsing = XML_PARSING; } @@ -2231,7 +2284,7 @@ doContent(XML_Parser parser, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);[](#l4.212)
entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);[](#l4.213) poolDiscard(&dtd->pool);[](#l4.214) /* First, determine if a check for an existing declaration is needed;[](#l4.215) if yes, check that the entity exists, and that it is internal,[](#l4.216)
@@ -2618,12 +2671,12 @@ storeAtts(XML_Parser parser, const ENCOD const XML_Char localPart; / lookup the element type name */
- elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0); if (!elementType) { const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); if (!name) return XML_ERROR_NO_MEMORY;
- elementType = (ELEMENT_TYPE )lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (!elementType) return XML_ERROR_NO_MEMORY; @@ -2792,9 +2845,9 @@ storeAtts(XML_Parser parser, const ENCOD if (s[-1] == 2) { / prefixed */ ATTRIBUTE_ID *id; const BINDING *b;
unsigned long uriHash = 0;[](#l4.236)
unsigned long uriHash = hash_secret_salt;[](#l4.237) ((XML_Char *)s)[-1] = 0; /* clear flag */[](#l4.238)
id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);[](#l4.239)
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);[](#l4.240) if (!id)[](#l4.241) return XML_ERROR_NO_MEMORY;[](#l4.242) b = id->prefix->binding;[](#l4.243)
@@ -2818,7 +2871,7 @@ storeAtts(XML_Parser parser, const ENCOD } while (s++); { / Check hash table for duplicate of expanded name (uriName).
Derived from code in lookup(HASH_TABLE *table, ...).[](#l4.248)
Derived from code in lookup(parser, HASH_TABLE *table, ...).[](#l4.249) */[](#l4.250) unsigned char step = 0;[](#l4.251) unsigned long mask = nsAttsSize - 1;[](#l4.252)
@@ -3756,7 +3809,8 @@ doProlog(XML_Parser parser, case XML_ROLE_DOCTYPE_PUBLIC_ID: #ifdef XML_DTD useForeignDTD = XML_FALSE;
declEntity = (ENTITY *)lookup(&dtd->paramEntities,[](#l4.257)
declEntity = (ENTITY *)lookup(parser,[](#l4.258)
&dtd->paramEntities,[](#l4.259) externalSubsetName,[](#l4.260) sizeof(ENTITY));[](#l4.261) if (!declEntity)[](#l4.262)
@@ -3811,7 +3865,8 @@ doProlog(XML_Parser parser, XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; dtd->hasParamEntityRefs = XML_TRUE; if (paramEntityParsing && externalEntityRefHandler) {
ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,[](#l4.267)
ENTITY *entity = (ENTITY *)lookup(parser,[](#l4.268)
&dtd->paramEntities,[](#l4.269) externalSubsetName,[](#l4.270) sizeof(ENTITY));[](#l4.271) if (!entity)[](#l4.272)
@@ -3855,7 +3910,7 @@ doProlog(XML_Parser parser, XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; dtd->hasParamEntityRefs = XML_TRUE; if (paramEntityParsing && externalEntityRefHandler) {
ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,[](#l4.277)
ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,[](#l4.278) externalSubsetName,[](#l4.279) sizeof(ENTITY));[](#l4.280) if (!entity)[](#l4.281)
@@ -4069,7 +4124,8 @@ doProlog(XML_Parser parser, break; #else /* XML_DTD */ if (!declEntity) {
declEntity = (ENTITY *)lookup(&dtd->paramEntities,[](#l4.286)
declEntity = (ENTITY *)lookup(parser,[](#l4.287)
&dtd->paramEntities,[](#l4.288) externalSubsetName,[](#l4.289) sizeof(ENTITY));[](#l4.290) if (!declEntity)[](#l4.291)
@@ -4144,7 +4200,7 @@ doProlog(XML_Parser parser, const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY;
declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,[](#l4.296)
declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,[](#l4.297) sizeof(ENTITY));[](#l4.298) if (!declEntity)[](#l4.299) return XML_ERROR_NO_MEMORY;[](#l4.300)
@@ -4176,7 +4232,7 @@ doProlog(XML_Parser parser, const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (!name) return XML_ERROR_NO_MEMORY;
declEntity = (ENTITY *)lookup(&dtd->paramEntities,[](#l4.305)
declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,[](#l4.306) name, sizeof(ENTITY));[](#l4.307) if (!declEntity)[](#l4.308) return XML_ERROR_NO_MEMORY;[](#l4.309)
@@ -4358,7 +4414,7 @@ doProlog(XML_Parser parser, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);[](#l4.314)
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);[](#l4.315) poolDiscard(&dtd->pool);[](#l4.316) /* first, determine if a check for an existing declaration is needed;[](#l4.317) if yes, check that the entity exists, and that it is internal,[](#l4.318)
@@ -4882,7 +4938,7 @@ appendAttributeValue(XML_Parser parser, next - enc->minBytesPerChar); if (!name) return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);[](#l4.323)
entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);[](#l4.324) poolDiscard(&temp2Pool);[](#l4.325) /* First, determine if a check for an existing declaration is needed;[](#l4.326) if yes, check that the entity exists, and that it is internal.[](#l4.327)
@@ -4991,7 +5047,7 @@ storeEntityValue(XML_Parser parser, result = XML_ERROR_NO_MEMORY; goto endEntityValue; }
entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);[](#l4.332)
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);[](#l4.333) poolDiscard(&tempPool);[](#l4.334) if (!entity) {[](#l4.335) /* not a well-formedness error - see XML 1.0: WFC Entity Declared */[](#l4.336)
@@ -5281,7 +5337,7 @@ setElementTypePrefix(XML_Parser parser, } if (!poolAppendChar(&dtd->pool, XML_T('\0'))) return 0;
prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),[](#l4.341)
prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),[](#l4.342) sizeof(PREFIX));[](#l4.343) if (!prefix)[](#l4.344) return 0;[](#l4.345)
@@ -5310,7 +5366,7 @@ getAttributeId(XML_Parser parser, const return NULL; /* skip quotation mark - its storage will be re-used (like in name[-1]) */ ++name;
- id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); if (!id) return NULL; if (id->name != name) @@ -5328,7 +5384,7 @@ getAttributeId(XML_Parser parser, const if (name[5] == XML_T('\0')) id->prefix = &dtd->defaultPrefix; else
id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));[](#l4.359)
} else { @@ -5343,7 +5399,7 @@ getAttributeId(XML_Parser parser, const } if (!poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL;id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));[](#l4.360) id->xmlns = XML_TRUE;[](#l4.361)
id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),[](#l4.368)
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),[](#l4.369) sizeof(PREFIX));[](#l4.370) if (!id->prefix)[](#l4.371) return NULL;[](#l4.372)
@@ -5441,7 +5497,7 @@ setContext(XML_Parser parser, const XML_ ENTITY *e; if (!poolAppendChar(&tempPool, XML_T('\0'))) return XML_FALSE;
e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);[](#l4.377)
e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);[](#l4.378) if (e)[](#l4.379) e->open = XML_TRUE;[](#l4.380) if (*s != XML_T('\0'))[](#l4.381)
@@ -5456,7 +5512,7 @@ setContext(XML_Parser parser, const XML_ else { if (!poolAppendChar(&tempPool, XML_T('\0'))) return XML_FALSE;
prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),[](#l4.386)
prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),[](#l4.387) sizeof(PREFIX));[](#l4.388) if (!prefix)[](#l4.389) return XML_FALSE;[](#l4.390)
@@ -5620,7 +5676,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, The new DTD has already been initialized. */ static int -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) +dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; @@ -5635,7 +5691,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, name = poolCopyString(&(newDtd->pool), oldP->name); if (!name) return 0;
- if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX))) return 0; } @@ -5657,7 +5713,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, if (!name) return 0; ++name;
- newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); if (!newA) return 0; @@ -5667,7 +5723,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, if (oldA->prefix == &oldDtd->defaultPrefix) newA->prefix = &newDtd->defaultPrefix; else
newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),[](#l4.422)
} } @@ -5686,7 +5742,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, name = poolCopyString(&(newDtd->pool), oldE->name); if (!name) return 0;newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),[](#l4.423) oldA->prefix->name, 0);[](#l4.424)
- newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); if (!newE) return 0; @@ -5700,14 +5756,14 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, } if (oldE->idAtt) newE->idAtt = (ATTRIBUTE_ID *)
lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);[](#l4.440)
newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; if (oldE->prefix)lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);[](#l4.441)
newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),[](#l4.444)
for (i = 0; i < newE->nDefaultAtts; i++) { newE->defaultAtts[i].id = (ATTRIBUTE_ID *)newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),[](#l4.445) oldE->prefix->name, 0);[](#l4.446)
lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);[](#l4.449)
lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);[](#l4.450) newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;[](#l4.451) if (oldE->defaultAtts[i].value) {[](#l4.452) newE->defaultAtts[i].value[](#l4.453)
@@ -5721,13 +5777,15 @@ dtdCopy(DTD *newDtd, const DTD oldDtd, } / Copy the entity tables. */
- if (!copyEntityTable(oldParser,
&(newDtd->generalEntities),[](#l4.460) &(newDtd->pool),[](#l4.461) &(oldDtd->generalEntities)))[](#l4.462) return 0;[](#l4.463)
- if (!copyEntityTable(oldParser,
&(newDtd->paramEntities),[](#l4.468) &(newDtd->pool),[](#l4.469) &(oldDtd->paramEntities)))[](#l4.470) return 0;[](#l4.471)
@@ -5750,7 +5808,8 @@ dtdCopy(DTD *newDtd, const DTD oldDtd, } / End dtdCopy */ static int -copyEntityTable(HASH_TABLE *newTable, +copyEntityTable(XML_Parser oldParser,
HASH_TABLE *newTable,[](#l4.478) STRING_POOL *newPool,[](#l4.479) const HASH_TABLE *oldTable)[](#l4.480)
{ @@ -5769,7 +5828,7 @@ copyEntityTable(HASH_TABLE *newTable, name = poolCopyString(newPool, oldE->name); if (!name) return 0;
- newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY)); if (!newE) return 0; if (oldE->systemId) { @@ -5827,16 +5886,16 @@ keyeq(KEY s1, KEY s2) }
static unsigned long FASTCALL -hash(KEY s) +hash(XML_Parser parser, KEY s) {
- unsigned long h = hash_secret_salt; while (*s) h = CHAR_HASH(h, *s++); return h; } static NAMED * -lookup(HASH_TABLE *table, KEY name, size_t createSize) +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { size_t i; if (table->size == 0) { @@ -5853,10 +5912,10 @@ lookup(HASH_TABLE *table, KEY name, size return NULL; } memset(table->v, 0, tsize);
- unsigned long h = hash(parser, name); unsigned long mask = (unsigned long)table->size - 1; unsigned char step = 0; i = h & mask; @@ -5882,7 +5941,7 @@ lookup(HASH_TABLE *table, KEY name, size memset(newV, 0, tsize); for (i = 0; i < table->size; i++) if (table->v[i]) {
unsigned long newHash = hash(table->v[i]->name);[](#l4.528)
unsigned long newHash = hash(parser, table->v[i]->name);[](#l4.529) size_t j = newHash & newMask;[](#l4.530) step = 0;[](#l4.531) while (newV[j]) {[](#l4.532)
@@ -6257,7 +6316,7 @@ getElementType(XML_Parser parser, if (!name) return NULL;
- ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (!ret) return NULL; if (ret->name != name)
--- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1156,6 +1156,8 @@ newxmlparseobject(char *encoding, char * else { self->itself = XML_ParserCreate(encoding); }