|
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) |