components/libexpat/patches/CVE-2012-0876.patch
branchs11-sru
changeset 2334 b52a7ffea126
equal deleted inserted replaced
2329:b5648e26057f 2334:b52a7ffea126
       
     1 
       
     2 https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-0876
       
     3 
       
     4 --- lib/expat.h.cve0876
       
     5 +++ lib/expat.h
       
     6 @@ -883,6 +883,15 @@ XMLPARSEAPI(int)
       
     7  XML_SetParamEntityParsing(XML_Parser parser,
       
     8                            enum XML_ParamEntityParsing parsing);
       
     9  
       
    10 +/* Sets the hash salt to use for internal hash calculations.
       
    11 +   Helps in preventing DoS attacks based on predicting hash
       
    12 +   function behavior. This must be called before parsing is started.
       
    13 +   Returns 1 if successful, 0 when called after parsing has started.
       
    14 +*/
       
    15 +XMLPARSEAPI(int)
       
    16 +XML_SetHashSalt(XML_Parser parser,
       
    17 +                unsigned long hash_salt);
       
    18 +
       
    19  /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
       
    20     XML_GetErrorCode returns information about the error.
       
    21  */
       
    22 --- lib/xmlparse.c.cve0876
       
    23 +++ lib/xmlparse.c
       
    24 @@ -5,6 +5,8 @@
       
    25  #include <stddef.h>
       
    26  #include <string.h>                     /* memset(), memcpy() */
       
    27  #include <assert.h>
       
    28 +#include <limits.h>                     /* UINT_MAX */
       
    29 +#include <time.h>                       /* time() */
       
    30  
       
    31  #define XML_BUILDING_EXPAT 1
       
    32  
       
    33 @@ -391,12 +393,13 @@ static void dtdReset(DTD *p, const XML_M
       
    34  static void
       
    35  dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
       
    36  static int
       
    37 -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
       
    38 +dtdCopy(XML_Parser oldParser,
       
    39 +        DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
       
    40  static int
       
    41 -copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
       
    42 -
       
    43 +copyEntityTable(XML_Parser oldParser,
       
    44 +                HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
       
    45  static NAMED *
       
    46 -lookup(HASH_TABLE *table, KEY name, size_t createSize);
       
    47 +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
       
    48  static void FASTCALL
       
    49  hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
       
    50  static void FASTCALL hashTableClear(HASH_TABLE *);
       
    51 @@ -429,11 +432,15 @@ static ELEMENT_TYPE *
       
    52  getElementType(XML_Parser parser, const ENCODING *enc,
       
    53                 const char *ptr, const char *end);
       
    54  
       
    55 +static unsigned long generate_hash_secret_salt(void);
       
    56 +static XML_Bool startParsing(XML_Parser parser);
       
    57 +
       
    58  static XML_Parser
       
    59  parserCreate(const XML_Char *encodingName,
       
    60               const XML_Memory_Handling_Suite *memsuite,
       
    61               const XML_Char *nameSep,
       
    62               DTD *dtd);
       
    63 +
       
    64  static void
       
    65  parserInit(XML_Parser parser, const XML_Char *encodingName);
       
    66  
       
    67 @@ -546,6 +553,7 @@ struct XML_ParserStruct {
       
    68    XML_Bool m_useForeignDTD;
       
    69    enum XML_ParamEntityParsing m_paramEntityParsing;
       
    70  #endif
       
    71 +  unsigned long m_hash_secret_salt;
       
    72  };
       
    73  
       
    74  #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
       
    75 @@ -653,6 +661,7 @@ struct XML_ParserStruct {
       
    76  #define useForeignDTD (parser->m_useForeignDTD)
       
    77  #define paramEntityParsing (parser->m_paramEntityParsing)
       
    78  #endif /* XML_DTD */
       
    79 +#define hash_secret_salt (parser->m_hash_secret_salt)
       
    80  
       
    81  XML_Parser XMLCALL
       
    82  XML_ParserCreate(const XML_Char *encodingName)
       
    83 @@ -677,22 +686,35 @@ static const XML_Char implicitContext[] 
       
    84    ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
       
    85  };
       
    86  
       
    87 +static unsigned long
       
    88 +generate_hash_secret_salt(void)
       
    89 +{
       
    90 +  unsigned int seed = time(NULL) % UINT_MAX;
       
    91 +  srand(seed);
       
    92 +  return rand();
       
    93 +}
       
    94 +
       
    95 +static XML_Bool  /* only valid for root parser */
       
    96 +startParsing(XML_Parser parser)
       
    97 +{
       
    98 +    /* hash functions must be initialized before setContext() is called */
       
    99 +    if (hash_secret_salt == 0)
       
   100 +      hash_secret_salt = generate_hash_secret_salt();
       
   101 +    if (ns) {
       
   102 +      /* implicit context only set for root parser, since child
       
   103 +         parsers (i.e. external entity parsers) will inherit it
       
   104 +      */
       
   105 +      return setContext(parser, implicitContext);
       
   106 +    }
       
   107 +    return XML_TRUE;
       
   108 +}
       
   109 +
       
   110  XML_Parser XMLCALL
       
   111  XML_ParserCreate_MM(const XML_Char *encodingName,
       
   112                      const XML_Memory_Handling_Suite *memsuite,
       
   113                      const XML_Char *nameSep)
       
   114  {
       
   115 -  XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
       
   116 -  if (parser != NULL && ns) {
       
   117 -    /* implicit context only set for root parser, since child
       
   118 -       parsers (i.e. external entity parsers) will inherit it
       
   119 -    */
       
   120 -    if (!setContext(parser, implicitContext)) {
       
   121 -      XML_ParserFree(parser);
       
   122 -      return NULL;
       
   123 -    }
       
   124 -  }
       
   125 -  return parser;
       
   126 +  return parserCreate(encodingName, memsuite, nameSep, NULL);
       
   127  }
       
   128  
       
   129  static XML_Parser
       
   130 @@ -866,6 +888,7 @@ parserInit(XML_Parser parser, const XML_
       
   131    useForeignDTD = XML_FALSE;
       
   132    paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
       
   133  #endif
       
   134 +  hash_secret_salt = 0;
       
   135  }
       
   136  
       
   137  /* moves list of bindings to freeBindingList */
       
   138 @@ -913,7 +936,7 @@ XML_ParserReset(XML_Parser parser, const
       
   139    poolClear(&temp2Pool);
       
   140    parserInit(parser, encodingName);
       
   141    dtdReset(_dtd, &parser->m_mem);
       
   142 -  return setContext(parser, implicitContext);
       
   143 +  return XML_TRUE;
       
   144  }
       
   145  
       
   146  enum XML_Status XMLCALL
       
   147 @@ -982,6 +1005,12 @@ XML_ExternalEntityParserCreate(XML_Parse
       
   148    int oldInEntityValue = prologState.inEntityValue;
       
   149  #endif
       
   150    XML_Bool oldns_triplets = ns_triplets;
       
   151 +  /* Note that the new parser shares the same hash secret as the old
       
   152 +     parser, so that dtdCopy and copyEntityTable can lookup values
       
   153 +     from hash tables associated with either parser without us having
       
   154 +     to worry which hash secrets each table has.
       
   155 +  */
       
   156 +  unsigned long oldhash_secret_salt = hash_secret_salt;
       
   157  
       
   158  #ifdef XML_DTD
       
   159    if (!context)
       
   160 @@ -1035,13 +1064,14 @@ XML_ExternalEntityParserCreate(XML_Parse
       
   161      externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
       
   162    defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
       
   163    ns_triplets = oldns_triplets;
       
   164 +  hash_secret_salt = oldhash_secret_salt;
       
   165    parentParser = oldParser;
       
   166  #ifdef XML_DTD
       
   167    paramEntityParsing = oldParamEntityParsing;
       
   168    prologState.inEntityValue = oldInEntityValue;
       
   169    if (context) {
       
   170  #endif /* XML_DTD */
       
   171 -    if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
       
   172 +    if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
       
   173        || !setContext(parser, context)) {
       
   174        XML_ParserFree(parser);
       
   175        return NULL;
       
   176 @@ -1426,6 +1456,17 @@ XML_SetParamEntityParsing(XML_Parser par
       
   177  #endif
       
   178  }
       
   179  
       
   180 +int XMLCALL
       
   181 +XML_SetHashSalt(XML_Parser parser,
       
   182 +                unsigned long hash_salt)
       
   183 +{
       
   184 +  /* block after XML_Parse()/XML_ParseBuffer() has been called */
       
   185 +  if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
       
   186 +    return 0;
       
   187 +  hash_secret_salt = hash_salt;
       
   188 +  return 1;
       
   189 +}
       
   190 +
       
   191  enum XML_Status XMLCALL
       
   192  XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
       
   193  {
       
   194 @@ -1436,6 +1477,11 @@ XML_Parse(XML_Parser parser, const char 
       
   195    case XML_FINISHED:
       
   196      errorCode = XML_ERROR_FINISHED;
       
   197      return XML_STATUS_ERROR;
       
   198 +  case XML_INITIALIZED:
       
   199 +    if (parentParser == NULL && !startParsing(parser)) {
       
   200 +      errorCode = XML_ERROR_NO_MEMORY;
       
   201 +      return XML_STATUS_ERROR;
       
   202 +    }
       
   203    default:
       
   204      ps_parsing = XML_PARSING;
       
   205    }
       
   206 @@ -1494,11 +1540,13 @@ XML_Parse(XML_Parser parser, const char 
       
   207          break;
       
   208        case XML_INITIALIZED:
       
   209        case XML_PARSING:
       
   210 -        result = XML_STATUS_OK;
       
   211          if (isFinal) {
       
   212            ps_parsing = XML_FINISHED;
       
   213 -          return result;
       
   214 +          return XML_STATUS_OK;
       
   215          }
       
   216 +      /* fall through */
       
   217 +      default:
       
   218 +        result = XML_STATUS_OK;
       
   219        }
       
   220      }
       
   221  
       
   222 @@ -1559,6 +1607,11 @@ XML_ParseBuffer(XML_Parser parser, int l
       
   223    case XML_FINISHED:
       
   224      errorCode = XML_ERROR_FINISHED;
       
   225      return XML_STATUS_ERROR;
       
   226 +  case XML_INITIALIZED:
       
   227 +    if (parentParser == NULL && !startParsing(parser)) {
       
   228 +      errorCode = XML_ERROR_NO_MEMORY;
       
   229 +      return XML_STATUS_ERROR;
       
   230 +    }
       
   231    default:
       
   232      ps_parsing = XML_PARSING;
       
   233    }
       
   234 @@ -2240,7 +2293,7 @@ doContent(XML_Parser parser,
       
   235                                  next - enc->minBytesPerChar);
       
   236          if (!name)
       
   237            return XML_ERROR_NO_MEMORY;
       
   238 -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
       
   239 +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
       
   240          poolDiscard(&dtd->pool);
       
   241          /* First, determine if a check for an existing declaration is needed;
       
   242             if yes, check that the entity exists, and that it is internal,
       
   243 @@ -2630,12 +2683,12 @@ storeAtts(XML_Parser parser, const ENCOD
       
   244    const XML_Char *localPart;
       
   245  
       
   246    /* lookup the element type name */
       
   247 -  elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
       
   248 +  elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
       
   249    if (!elementType) {
       
   250      const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
       
   251      if (!name)
       
   252        return XML_ERROR_NO_MEMORY;
       
   253 -    elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
       
   254 +    elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
       
   255                                           sizeof(ELEMENT_TYPE));
       
   256      if (!elementType)
       
   257        return XML_ERROR_NO_MEMORY;
       
   258 @@ -2804,9 +2857,9 @@ storeAtts(XML_Parser parser, const ENCOD
       
   259        if (s[-1] == 2) {  /* prefixed */
       
   260          ATTRIBUTE_ID *id;
       
   261          const BINDING *b;
       
   262 -        unsigned long uriHash = 0;
       
   263 +        unsigned long uriHash = hash_secret_salt;
       
   264          ((XML_Char *)s)[-1] = 0;  /* clear flag */
       
   265 -        id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
       
   266 +        id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
       
   267          b = id->prefix->binding;
       
   268          if (!b)
       
   269            return XML_ERROR_UNBOUND_PREFIX;
       
   270 @@ -2828,7 +2881,7 @@ storeAtts(XML_Parser parser, const ENCOD
       
   271          } while (*s++);
       
   272  
       
   273          { /* Check hash table for duplicate of expanded name (uriName).
       
   274 -             Derived from code in lookup(HASH_TABLE *table, ...).
       
   275 +             Derived from code in lookup(parser, HASH_TABLE *table, ...).
       
   276            */
       
   277            unsigned char step = 0;
       
   278            unsigned long mask = nsAttsSize - 1;
       
   279 @@ -3777,7 +3830,8 @@ doProlog(XML_Parser parser,
       
   280      case XML_ROLE_DOCTYPE_PUBLIC_ID:
       
   281  #ifdef XML_DTD
       
   282        useForeignDTD = XML_FALSE;
       
   283 -      declEntity = (ENTITY *)lookup(&dtd->paramEntities,
       
   284 +      declEntity = (ENTITY *)lookup(parser,
       
   285 +                                    &dtd->paramEntities,
       
   286                                      externalSubsetName,
       
   287                                      sizeof(ENTITY));
       
   288        if (!declEntity)
       
   289 @@ -3832,7 +3886,8 @@ doProlog(XML_Parser parser,
       
   290          XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
       
   291          dtd->hasParamEntityRefs = XML_TRUE;
       
   292          if (paramEntityParsing && externalEntityRefHandler) {
       
   293 -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
       
   294 +          ENTITY *entity = (ENTITY *)lookup(parser,
       
   295 +                                            &dtd->paramEntities,
       
   296                                              externalSubsetName,
       
   297                                              sizeof(ENTITY));
       
   298            if (!entity)
       
   299 @@ -3876,7 +3931,7 @@ doProlog(XML_Parser parser,
       
   300          XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
       
   301          dtd->hasParamEntityRefs = XML_TRUE;
       
   302          if (paramEntityParsing && externalEntityRefHandler) {
       
   303 -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
       
   304 +          ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
       
   305                                              externalSubsetName,
       
   306                                              sizeof(ENTITY));
       
   307            if (!entity)
       
   308 @@ -4090,7 +4145,8 @@ doProlog(XML_Parser parser,
       
   309        break;
       
   310  #else /* XML_DTD */
       
   311        if (!declEntity) {
       
   312 -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
       
   313 +        declEntity = (ENTITY *)lookup(parser,
       
   314 +                                      &dtd->paramEntities,
       
   315                                        externalSubsetName,
       
   316                                        sizeof(ENTITY));
       
   317          if (!declEntity)
       
   318 @@ -4165,7 +4221,7 @@ doProlog(XML_Parser parser,
       
   319            const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
       
   320            if (!name)
       
   321              return XML_ERROR_NO_MEMORY;
       
   322 -          declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
       
   323 +          declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
       
   324                                          sizeof(ENTITY));
       
   325            if (!declEntity)
       
   326              return XML_ERROR_NO_MEMORY;
       
   327 @@ -4197,7 +4253,7 @@ doProlog(XML_Parser parser,
       
   328          const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
       
   329          if (!name)
       
   330            return XML_ERROR_NO_MEMORY;
       
   331 -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
       
   332 +        declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
       
   333                                             name, sizeof(ENTITY));
       
   334          if (!declEntity)
       
   335            return XML_ERROR_NO_MEMORY;
       
   336 @@ -4379,7 +4435,7 @@ doProlog(XML_Parser parser,
       
   337                                  next - enc->minBytesPerChar);
       
   338          if (!name)
       
   339            return XML_ERROR_NO_MEMORY;
       
   340 -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
       
   341 +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
       
   342          poolDiscard(&dtd->pool);
       
   343          /* first, determine if a check for an existing declaration is needed;
       
   344             if yes, check that the entity exists, and that it is internal,
       
   345 @@ -4903,7 +4959,7 @@ appendAttributeValue(XML_Parser parser, 
       
   346                                 next - enc->minBytesPerChar);
       
   347          if (!name)
       
   348            return XML_ERROR_NO_MEMORY;
       
   349 -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
       
   350 +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
       
   351          poolDiscard(&temp2Pool);
       
   352          /* First, determine if a check for an existing declaration is needed;
       
   353             if yes, check that the entity exists, and that it is internal.
       
   354 @@ -5012,7 +5068,7 @@ storeEntityValue(XML_Parser parser,
       
   355            result = XML_ERROR_NO_MEMORY;
       
   356            goto endEntityValue;
       
   357          }
       
   358 -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
       
   359 +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
       
   360          poolDiscard(&tempPool);
       
   361          if (!entity) {
       
   362            /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
       
   363 @@ -5302,7 +5358,7 @@ setElementTypePrefix(XML_Parser parser, 
       
   364        }
       
   365        if (!poolAppendChar(&dtd->pool, XML_T('\0')))
       
   366          return 0;
       
   367 -      prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
       
   368 +      prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
       
   369                                  sizeof(PREFIX));
       
   370        if (!prefix)
       
   371          return 0;
       
   372 @@ -5331,7 +5387,7 @@ getAttributeId(XML_Parser parser, const 
       
   373      return NULL;
       
   374    /* skip quotation mark - its storage will be re-used (like in name[-1]) */
       
   375    ++name;
       
   376 -  id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
       
   377 +  id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
       
   378    if (!id)
       
   379      return NULL;
       
   380    if (id->name != name)
       
   381 @@ -5349,7 +5405,7 @@ getAttributeId(XML_Parser parser, const 
       
   382        if (name[5] == XML_T('\0'))
       
   383          id->prefix = &dtd->defaultPrefix;
       
   384        else
       
   385 -        id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
       
   386 +        id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
       
   387        id->xmlns = XML_TRUE;
       
   388      }
       
   389      else {
       
   390 @@ -5364,7 +5420,7 @@ getAttributeId(XML_Parser parser, const 
       
   391            }
       
   392            if (!poolAppendChar(&dtd->pool, XML_T('\0')))
       
   393              return NULL;
       
   394 -          id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
       
   395 +          id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
       
   396                                          sizeof(PREFIX));
       
   397            if (id->prefix->name == poolStart(&dtd->pool))
       
   398              poolFinish(&dtd->pool);
       
   399 @@ -5460,7 +5516,7 @@ setContext(XML_Parser parser, const XML_
       
   400        ENTITY *e;
       
   401        if (!poolAppendChar(&tempPool, XML_T('\0')))
       
   402          return XML_FALSE;
       
   403 -      e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
       
   404 +      e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
       
   405        if (e)
       
   406          e->open = XML_TRUE;
       
   407        if (*s != XML_T('\0'))
       
   408 @@ -5475,7 +5531,7 @@ setContext(XML_Parser parser, const XML_
       
   409        else {
       
   410          if (!poolAppendChar(&tempPool, XML_T('\0')))
       
   411            return XML_FALSE;
       
   412 -        prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
       
   413 +        prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
       
   414                                    sizeof(PREFIX));
       
   415          if (!prefix)
       
   416            return XML_FALSE;
       
   417 @@ -5639,7 +5695,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity,
       
   418     The new DTD has already been initialized.
       
   419  */
       
   420  static int
       
   421 -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
       
   422 +dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
       
   423  {
       
   424    HASH_TABLE_ITER iter;
       
   425  
       
   426 @@ -5654,7 +5710,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   427      name = poolCopyString(&(newDtd->pool), oldP->name);
       
   428      if (!name)
       
   429        return 0;
       
   430 -    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
       
   431 +    if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
       
   432        return 0;
       
   433    }
       
   434  
       
   435 @@ -5676,7 +5732,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   436      if (!name)
       
   437        return 0;
       
   438      ++name;
       
   439 -    newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
       
   440 +    newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
       
   441                                    sizeof(ATTRIBUTE_ID));
       
   442      if (!newA)
       
   443        return 0;
       
   444 @@ -5686,7 +5742,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   445        if (oldA->prefix == &oldDtd->defaultPrefix)
       
   446          newA->prefix = &newDtd->defaultPrefix;
       
   447        else
       
   448 -        newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
       
   449 +        newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
       
   450                                          oldA->prefix->name, 0);
       
   451      }
       
   452    }
       
   453 @@ -5705,7 +5761,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   454      name = poolCopyString(&(newDtd->pool), oldE->name);
       
   455      if (!name)
       
   456        return 0;
       
   457 -    newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
       
   458 +    newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
       
   459                                    sizeof(ELEMENT_TYPE));
       
   460      if (!newE)
       
   461        return 0;
       
   462 @@ -5719,14 +5775,14 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   463      }
       
   464      if (oldE->idAtt)
       
   465        newE->idAtt = (ATTRIBUTE_ID *)
       
   466 -          lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
       
   467 +          lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
       
   468      newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
       
   469      if (oldE->prefix)
       
   470 -      newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
       
   471 +      newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
       
   472                                        oldE->prefix->name, 0);
       
   473      for (i = 0; i < newE->nDefaultAtts; i++) {
       
   474        newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
       
   475 -          lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
       
   476 +          lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
       
   477        newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
       
   478        if (oldE->defaultAtts[i].value) {
       
   479          newE->defaultAtts[i].value
       
   480 @@ -5740,13 +5796,15 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   481    }
       
   482  
       
   483    /* Copy the entity tables. */
       
   484 -  if (!copyEntityTable(&(newDtd->generalEntities),
       
   485 +  if (!copyEntityTable(oldParser,
       
   486 +                       &(newDtd->generalEntities),
       
   487                         &(newDtd->pool),
       
   488                         &(oldDtd->generalEntities)))
       
   489        return 0;
       
   490  
       
   491  #ifdef XML_DTD
       
   492 -  if (!copyEntityTable(&(newDtd->paramEntities),
       
   493 +  if (!copyEntityTable(oldParser,
       
   494 +                       &(newDtd->paramEntities),
       
   495                         &(newDtd->pool),
       
   496                         &(oldDtd->paramEntities)))
       
   497        return 0;
       
   498 @@ -5769,7 +5827,8 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, 
       
   499  }  /* End dtdCopy */
       
   500  
       
   501  static int
       
   502 -copyEntityTable(HASH_TABLE *newTable,
       
   503 +copyEntityTable(XML_Parser oldParser,
       
   504 +                HASH_TABLE *newTable,
       
   505                  STRING_POOL *newPool,
       
   506                  const HASH_TABLE *oldTable)
       
   507  {
       
   508 @@ -5788,7 +5847,7 @@ copyEntityTable(HASH_TABLE *newTable,
       
   509      name = poolCopyString(newPool, oldE->name);
       
   510      if (!name)
       
   511        return 0;
       
   512 -    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
       
   513 +    newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
       
   514      if (!newE)
       
   515        return 0;
       
   516      if (oldE->systemId) {
       
   517 @@ -5846,16 +5905,16 @@ keyeq(KEY s1, KEY s2)
       
   518  }
       
   519  
       
   520  static unsigned long FASTCALL
       
   521 -hash(KEY s)
       
   522 +hash(XML_Parser parser, KEY s)
       
   523  {
       
   524 -  unsigned long h = 0;
       
   525 +  unsigned long h = hash_secret_salt;
       
   526    while (*s)
       
   527      h = CHAR_HASH(h, *s++);
       
   528    return h;
       
   529  }
       
   530  
       
   531  static NAMED *
       
   532 -lookup(HASH_TABLE *table, KEY name, size_t createSize)
       
   533 +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
       
   534  {
       
   535    size_t i;
       
   536    if (table->size == 0) {
       
   537 @@ -5872,10 +5931,10 @@ lookup(HASH_TABLE *table, KEY name, size
       
   538        return NULL;
       
   539      }
       
   540      memset(table->v, 0, tsize);
       
   541 -    i = hash(name) & ((unsigned long)table->size - 1);
       
   542 +    i = hash(parser, name) & ((unsigned long)table->size - 1);
       
   543    }
       
   544    else {
       
   545 -    unsigned long h = hash(name);
       
   546 +    unsigned long h = hash(parser, name);
       
   547      unsigned long mask = (unsigned long)table->size - 1;
       
   548      unsigned char step = 0;
       
   549      i = h & mask;
       
   550 @@ -5901,7 +5960,7 @@ lookup(HASH_TABLE *table, KEY name, size
       
   551        memset(newV, 0, tsize);
       
   552        for (i = 0; i < table->size; i++)
       
   553          if (table->v[i]) {
       
   554 -          unsigned long newHash = hash(table->v[i]->name);
       
   555 +          unsigned long newHash = hash(parser, table->v[i]->name);
       
   556            size_t j = newHash & newMask;
       
   557            step = 0;
       
   558            while (newV[j]) {
       
   559 @@ -6276,7 +6335,7 @@ getElementType(XML_Parser parser,
       
   560  
       
   561    if (!name)
       
   562      return NULL;
       
   563 -  ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
       
   564 +  ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
       
   565    if (!ret)
       
   566      return NULL;
       
   567    if (ret->name != name)