Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: third_party/libxml/src/dict.c

Issue 1193533007: Upgrade to libxml 2.9.2 and libxslt 1.1.28 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: no iconv Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libxml/src/depcomp ('k') | third_party/libxml/src/elfgcchack.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * dict.c: dictionary of reusable strings, just used to avoid allocation 2 * dict.c: dictionary of reusable strings, just used to avoid allocation
3 * and freeing operations. 3 * and freeing operations.
4 * 4 *
5 * Copyright (C) 2003 Daniel Veillard. 5 * Copyright (C) 2003-2012 Daniel Veillard.
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 12 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 13 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 14 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15 * 15 *
16 * Author: daniel@veillard.com 16 * Author: daniel@veillard.com
17 */ 17 */
18 18
19 #define IN_LIBXML 19 #define IN_LIBXML
20 #include "libxml.h" 20 #include "libxml.h"
21 21
22 #include <limits.h>
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_TIME_H
27 #include <time.h>
28 #endif
29
30 /*
31 * Following http://www.ocert.org/advisories/ocert-2011-003.html
32 * it seems that having hash randomization might be a good idea
33 * when using XML with untrusted data
34 * Note1: that it works correctly only if compiled with WITH_BIG_KEY
35 * which is the default.
36 * Note2: the fast function used for a small dict won't protect very
37 * well but since the attack is based on growing a very big hash
38 * list we will use the BigKey algo as soon as the hash size grows
39 * over MIN_DICT_SIZE so this actually works
40 */
41 #if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
42 #define DICT_RANDOMIZATION
43 #endif
44
22 #include <string.h> 45 #include <string.h>
23 #ifdef HAVE_STDINT_H 46 #ifdef HAVE_STDINT_H
24 #include <stdint.h> 47 #include <stdint.h>
25 #else 48 #else
26 #ifdef HAVE_INTTYPES_H 49 #ifdef HAVE_INTTYPES_H
27 #include <inttypes.h> 50 #include <inttypes.h>
28 #elif defined(WIN32) 51 #elif defined(WIN32)
29 typedef unsigned __int32 uint32_t; 52 typedef unsigned __int32 uint32_t;
30 #endif 53 #endif
31 #endif 54 #endif
32 #include <libxml/tree.h> 55 #include <libxml/tree.h>
33 #include <libxml/dict.h> 56 #include <libxml/dict.h>
34 #include <libxml/xmlmemory.h> 57 #include <libxml/xmlmemory.h>
35 #include <libxml/xmlerror.h> 58 #include <libxml/xmlerror.h>
36 #include <libxml/globals.h> 59 #include <libxml/globals.h>
37 60
38 /* #define DEBUG_GROW */ 61 /* #define DEBUG_GROW */
39 /* #define DICT_DEBUG_PATTERNS */ 62 /* #define DICT_DEBUG_PATTERNS */
40 63
41 #define MAX_HASH_LEN 3 64 #define MAX_HASH_LEN 3
42 #define MIN_DICT_SIZE 128 65 #define MIN_DICT_SIZE 128
43 #define MAX_DICT_HASH 8 * 2048 66 #define MAX_DICT_HASH 8 * 2048
44 #define WITH_BIG_KEY 67 #define WITH_BIG_KEY
45 68
46 #ifdef WITH_BIG_KEY 69 #ifdef WITH_BIG_KEY
47 #define xmlDictComputeKey(dict, name, len)» » » \ 70 #define xmlDictComputeKey(dict, name, len) \
48 (((dict)->size == MIN_DICT_SIZE) ?» » » » \ 71 (((dict)->size == MIN_DICT_SIZE) ? \
49 xmlDictComputeFastKey(name, len) :»» » » \ 72 xmlDictComputeFastKey(name, len, (dict)->seed) : \
50 xmlDictComputeBigKey(name, len)) 73 xmlDictComputeBigKey(name, len, (dict)->seed))
51 74
52 #define xmlDictComputeQKey(dict, prefix, plen, name, len)» \ 75 #define xmlDictComputeQKey(dict, prefix, plen, name, len) \
53 (((prefix) == NULL) ?» » » » » \ 76 (((prefix) == NULL) ? \
54 (xmlDictComputeKey(dict, name, len)) :» » » \ 77 (xmlDictComputeKey(dict, name, len)) : \
55 (((dict)->size == MIN_DICT_SIZE) ?» » » \ 78 (((dict)->size == MIN_DICT_SIZE) ? \
56 xmlDictComputeFastQKey(prefix, plen, name, len) :» \ 79 xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) :» \
57 xmlDictComputeBigQKey(prefix, plen, name, len))) 80 xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
58 81
59 #else /* !WITH_BIG_KEY */ 82 #else /* !WITH_BIG_KEY */
60 #define xmlDictComputeKey(dict, name, len)» » » \ 83 #define xmlDictComputeKey(dict, name, len) \
61 xmlDictComputeFastKey(name, len) 84 xmlDictComputeFastKey(name, len, (dict)->seed)
62 #define xmlDictComputeQKey(dict, prefix, plen, name, len)» \ 85 #define xmlDictComputeQKey(dict, prefix, plen, name, len) \
63 xmlDictComputeFastQKey(prefix, plen, name, len) 86 xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
64 #endif /* WITH_BIG_KEY */ 87 #endif /* WITH_BIG_KEY */
65 88
66 /* 89 /*
67 * An entry in the dictionnary 90 * An entry in the dictionnary
68 */ 91 */
69 typedef struct _xmlDictEntry xmlDictEntry; 92 typedef struct _xmlDictEntry xmlDictEntry;
70 typedef xmlDictEntry *xmlDictEntryPtr; 93 typedef xmlDictEntry *xmlDictEntryPtr;
71 struct _xmlDictEntry { 94 struct _xmlDictEntry {
72 struct _xmlDictEntry *next; 95 struct _xmlDictEntry *next;
73 const xmlChar *name; 96 const xmlChar *name;
74 int len; 97 unsigned int len;
75 int valid; 98 int valid;
76 unsigned long okey; 99 unsigned long okey;
77 }; 100 };
78 101
79 typedef struct _xmlDictStrings xmlDictStrings; 102 typedef struct _xmlDictStrings xmlDictStrings;
80 typedef xmlDictStrings *xmlDictStringsPtr; 103 typedef xmlDictStrings *xmlDictStringsPtr;
81 struct _xmlDictStrings { 104 struct _xmlDictStrings {
82 xmlDictStringsPtr next; 105 xmlDictStringsPtr next;
83 xmlChar *free; 106 xmlChar *free;
84 xmlChar *end; 107 xmlChar *end;
85 int size; 108 size_t size;
86 int nbStrings; 109 size_t nbStrings;
87 xmlChar array[1]; 110 xmlChar array[1];
88 }; 111 };
89 /* 112 /*
90 * The entire dictionnary 113 * The entire dictionnary
91 */ 114 */
92 struct _xmlDict { 115 struct _xmlDict {
93 int ref_counter; 116 int ref_counter;
94 117
95 struct _xmlDictEntry *dict; 118 struct _xmlDictEntry *dict;
96 int size; 119 size_t size;
97 int nbElems; 120 unsigned int nbElems;
98 xmlDictStringsPtr strings; 121 xmlDictStringsPtr strings;
99 122
100 struct _xmlDict *subdict; 123 struct _xmlDict *subdict;
124 /* used for randomization */
125 int seed;
126 /* used to impose a limit on size */
127 size_t limit;
101 }; 128 };
102 129
103 /* 130 /*
104 * A mutex for modifying the reference counter for shared 131 * A mutex for modifying the reference counter for shared
105 * dictionaries. 132 * dictionaries.
106 */ 133 */
107 static xmlRMutexPtr xmlDictMutex = NULL; 134 static xmlRMutexPtr xmlDictMutex = NULL;
108 135
109 /* 136 /*
110 * Whether the dictionary mutex was initialized. 137 * Whether the dictionary mutex was initialized.
111 */ 138 */
112 static int xmlDictInitialized = 0; 139 static int xmlDictInitialized = 0;
113 140
141 #ifdef DICT_RANDOMIZATION
142 #ifdef HAVE_RAND_R
143 /*
144 * Internal data for random function, protected by xmlDictMutex
145 */
146 static unsigned int rand_seed = 0;
147 #endif
148 #endif
149
114 /** 150 /**
115 * xmlInitializeDict: 151 * xmlInitializeDict:
116 * 152 *
117 * Do the dictionary mutex initialization. 153 * Do the dictionary mutex initialization.
154 * this function is deprecated
155 *
156 * Returns 0 if initialization was already done, and 1 if that
157 * call led to the initialization
158 */
159 int xmlInitializeDict(void) {
160 return(0);
161 }
162
163 /**
164 * __xmlInitializeDict:
165 *
166 * This function is not public
167 * Do the dictionary mutex initialization.
118 * this function is not thread safe, initialization should 168 * this function is not thread safe, initialization should
119 * preferably be done once at startup 169 * normally be done once at setup when called from xmlOnceInit()
170 * we may also land in this code if thread support is not compiled in
171 *
172 * Returns 0 if initialization was already done, and 1 if that
173 * call led to the initialization
120 */ 174 */
121 static int xmlInitializeDict(void) { 175 int __xmlInitializeDict(void) {
122 if (xmlDictInitialized) 176 if (xmlDictInitialized)
123 return(1); 177 return(1);
124 178
125 if ((xmlDictMutex = xmlNewRMutex()) == NULL) 179 if ((xmlDictMutex = xmlNewRMutex()) == NULL)
126 return(0); 180 return(0);
181 xmlRMutexLock(xmlDictMutex);
127 182
183 #ifdef DICT_RANDOMIZATION
184 #ifdef HAVE_RAND_R
185 rand_seed = time(NULL);
186 rand_r(& rand_seed);
187 #else
188 srand(time(NULL));
189 #endif
190 #endif
128 xmlDictInitialized = 1; 191 xmlDictInitialized = 1;
192 xmlRMutexUnlock(xmlDictMutex);
129 return(1); 193 return(1);
130 } 194 }
131 195
196 #ifdef DICT_RANDOMIZATION
197 int __xmlRandom(void) {
198 int ret;
199
200 if (xmlDictInitialized == 0)
201 __xmlInitializeDict();
202
203 xmlRMutexLock(xmlDictMutex);
204 #ifdef HAVE_RAND_R
205 ret = rand_r(& rand_seed);
206 #else
207 ret = rand();
208 #endif
209 xmlRMutexUnlock(xmlDictMutex);
210 return(ret);
211 }
212 #endif
213
132 /** 214 /**
133 * xmlDictCleanup: 215 * xmlDictCleanup:
134 * 216 *
135 * Free the dictionary mutex. 217 * Free the dictionary mutex. Do not call unless sure the library
218 * is not in use anymore !
136 */ 219 */
137 void 220 void
138 xmlDictCleanup(void) { 221 xmlDictCleanup(void) {
139 if (!xmlDictInitialized) 222 if (!xmlDictInitialized)
140 return; 223 return;
141 224
142 xmlFreeRMutex(xmlDictMutex); 225 xmlFreeRMutex(xmlDictMutex);
143 226
144 xmlDictInitialized = 0; 227 xmlDictInitialized = 0;
145 } 228 }
146 229
147 /* 230 /*
148 * xmlDictAddString: 231 * xmlDictAddString:
149 * @dict: the dictionnary 232 * @dict: the dictionnary
150 * @name: the name of the userdata 233 * @name: the name of the userdata
151 * @len: the length of the name, if -1 it is recomputed 234 * @len: the length of the name
152 * 235 *
153 * Add the string to the array[s] 236 * Add the string to the array[s]
154 * 237 *
155 * Returns the pointer of the local string, or NULL in case of error. 238 * Returns the pointer of the local string, or NULL in case of error.
156 */ 239 */
157 static const xmlChar * 240 static const xmlChar *
158 xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { 241 xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
159 xmlDictStringsPtr pool; 242 xmlDictStringsPtr pool;
160 const xmlChar *ret; 243 const xmlChar *ret;
161 int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ 244 size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
245 size_t limit = 0;
162 246
163 #ifdef DICT_DEBUG_PATTERNS 247 #ifdef DICT_DEBUG_PATTERNS
164 fprintf(stderr, "-"); 248 fprintf(stderr, "-");
165 #endif 249 #endif
166 pool = dict->strings; 250 pool = dict->strings;
167 while (pool != NULL) { 251 while (pool != NULL) {
168 if (pool->end - pool->free > namelen) 252 if (pool->end - pool->free > namelen)
169 goto found_pool; 253 goto found_pool;
170 if (pool->size > size) size = pool->size; 254 if (pool->size > size) size = pool->size;
255 limit += pool->size;
171 pool = pool->next; 256 pool = pool->next;
172 } 257 }
173 /* 258 /*
174 * Not found, need to allocate 259 * Not found, need to allocate
175 */ 260 */
176 if (pool == NULL) { 261 if (pool == NULL) {
262 if ((dict->limit > 0) && (limit > dict->limit)) {
263 return(NULL);
264 }
265
177 if (size == 0) size = 1000; 266 if (size == 0) size = 1000;
178 else size *= 4; /* exponential growth */ 267 else size *= 4; /* exponential growth */
179 if (size < 4 * namelen) 268 if (size < 4 * namelen)
180 size = 4 * namelen; /* just in case ! */ 269 size = 4 * namelen; /* just in case ! */
181 pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); 270 pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
182 if (pool == NULL) 271 if (pool == NULL)
183 return(NULL); 272 return(NULL);
184 pool->size = size; 273 pool->size = size;
185 pool->nbStrings = 0; 274 pool->nbStrings = 0;
186 pool->free = &pool->array[0]; 275 pool->free = &pool->array[0];
187 pool->end = &pool->array[size]; 276 pool->end = &pool->array[size];
188 pool->next = dict->strings; 277 pool->next = dict->strings;
189 dict->strings = pool; 278 dict->strings = pool;
190 #ifdef DICT_DEBUG_PATTERNS 279 #ifdef DICT_DEBUG_PATTERNS
191 fprintf(stderr, "+"); 280 fprintf(stderr, "+");
192 #endif 281 #endif
193 } 282 }
194 found_pool: 283 found_pool:
195 ret = pool->free; 284 ret = pool->free;
196 memcpy(pool->free, name, namelen); 285 memcpy(pool->free, name, namelen);
197 pool->free += namelen; 286 pool->free += namelen;
198 *(pool->free++) = 0; 287 *(pool->free++) = 0;
199 pool->nbStrings++; 288 pool->nbStrings++;
200 return(ret); 289 return(ret);
201 } 290 }
202 291
203 /* 292 /*
204 * xmlDictAddQString: 293 * xmlDictAddQString:
205 * @dict: the dictionnary 294 * @dict: the dictionnary
206 * @prefix: the prefix of the userdata 295 * @prefix: the prefix of the userdata
207 * @plen: the prefix length 296 * @plen: the prefix length
208 * @name: the name of the userdata 297 * @name: the name of the userdata
209 * @len: the length of the name, if -1 it is recomputed 298 * @len: the length of the name
210 * 299 *
211 * Add the QName to the array[s] 300 * Add the QName to the array[s]
212 * 301 *
213 * Returns the pointer of the local string, or NULL in case of error. 302 * Returns the pointer of the local string, or NULL in case of error.
214 */ 303 */
215 static const xmlChar * 304 static const xmlChar *
216 xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen, 305 xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
217 const xmlChar *name, int namelen) 306 const xmlChar *name, unsigned int namelen)
218 { 307 {
219 xmlDictStringsPtr pool; 308 xmlDictStringsPtr pool;
220 const xmlChar *ret; 309 const xmlChar *ret;
221 int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ 310 size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
311 size_t limit = 0;
222 312
223 if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); 313 if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
224 314
225 #ifdef DICT_DEBUG_PATTERNS 315 #ifdef DICT_DEBUG_PATTERNS
226 fprintf(stderr, "="); 316 fprintf(stderr, "=");
227 #endif 317 #endif
228 pool = dict->strings; 318 pool = dict->strings;
229 while (pool != NULL) { 319 while (pool != NULL) {
230 if (pool->end - pool->free > namelen + plen + 1) 320 if (pool->end - pool->free > namelen + plen + 1)
231 goto found_pool; 321 goto found_pool;
232 if (pool->size > size) size = pool->size; 322 if (pool->size > size) size = pool->size;
323 limit += pool->size;
233 pool = pool->next; 324 pool = pool->next;
234 } 325 }
235 /* 326 /*
236 * Not found, need to allocate 327 * Not found, need to allocate
237 */ 328 */
238 if (pool == NULL) { 329 if (pool == NULL) {
330 if ((dict->limit > 0) && (limit > dict->limit)) {
331 return(NULL);
332 }
333
239 if (size == 0) size = 1000; 334 if (size == 0) size = 1000;
240 else size *= 4; /* exponential growth */ 335 else size *= 4; /* exponential growth */
241 if (size < 4 * (namelen + plen + 1)) 336 if (size < 4 * (namelen + plen + 1))
242 size = 4 * (namelen + plen + 1); /* just in case ! */ 337 size = 4 * (namelen + plen + 1); /* just in case ! */
243 pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); 338 pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
244 if (pool == NULL) 339 if (pool == NULL)
245 return(NULL); 340 return(NULL);
246 pool->size = size; 341 pool->size = size;
247 pool->nbStrings = 0; 342 pool->nbStrings = 0;
248 pool->free = &pool->array[0]; 343 pool->free = &pool->array[0];
(...skipping 21 matching lines...) Expand all
270 * xmlDictComputeBigKey: 365 * xmlDictComputeBigKey:
271 * 366 *
272 * Calculate a hash key using a good hash function that works well for 367 * Calculate a hash key using a good hash function that works well for
273 * larger hash table sizes. 368 * larger hash table sizes.
274 * 369 *
275 * Hash function by "One-at-a-Time Hash" see 370 * Hash function by "One-at-a-Time Hash" see
276 * http://burtleburtle.net/bob/hash/doobs.html 371 * http://burtleburtle.net/bob/hash/doobs.html
277 */ 372 */
278 373
279 static uint32_t 374 static uint32_t
280 xmlDictComputeBigKey(const xmlChar* data, int namelen) { 375 xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
281 uint32_t hash; 376 uint32_t hash;
282 int i; 377 int i;
283 378
284 if (namelen <= 0 || data == NULL) return(0); 379 if (namelen <= 0 || data == NULL) return(0);
285 380
286 hash = 0; 381 hash = seed;
287 382
288 for (i = 0;i < namelen; i++) { 383 for (i = 0;i < namelen; i++) {
289 hash += data[i]; 384 hash += data[i];
290 hash += (hash << 10); 385 hash += (hash << 10);
291 hash ^= (hash >> 6); 386 hash ^= (hash >> 6);
292 } 387 }
293 hash += (hash << 3); 388 hash += (hash << 3);
294 hash ^= (hash >> 11); 389 hash ^= (hash >> 11);
295 hash += (hash << 15); 390 hash += (hash << 15);
296 391
297 return hash; 392 return hash;
298 } 393 }
299 394
300 /* 395 /*
301 * xmlDictComputeBigQKey: 396 * xmlDictComputeBigQKey:
302 * 397 *
303 * Calculate a hash key for two strings using a good hash function 398 * Calculate a hash key for two strings using a good hash function
304 * that works well for larger hash table sizes. 399 * that works well for larger hash table sizes.
305 * 400 *
306 * Hash function by "One-at-a-Time Hash" see 401 * Hash function by "One-at-a-Time Hash" see
307 * http://burtleburtle.net/bob/hash/doobs.html 402 * http://burtleburtle.net/bob/hash/doobs.html
308 * 403 *
309 * Neither of the two strings must be NULL. 404 * Neither of the two strings must be NULL.
310 */ 405 */
311 static unsigned long 406 static unsigned long
312 xmlDictComputeBigQKey(const xmlChar *prefix, int plen, 407 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
313 const xmlChar *name, int len) 408 const xmlChar *name, int len, int seed)
314 { 409 {
315 uint32_t hash; 410 uint32_t hash;
316 int i; 411 int i;
317 412
318 hash = 0; 413 hash = seed;
319 414
320 for (i = 0;i < plen; i++) { 415 for (i = 0;i < plen; i++) {
321 hash += prefix[i]; 416 hash += prefix[i];
322 hash += (hash << 10); 417 hash += (hash << 10);
323 hash ^= (hash >> 6); 418 hash ^= (hash >> 6);
324 } 419 }
325 hash += ':'; 420 hash += ':';
326 hash += (hash << 10); 421 hash += (hash << 10);
327 hash ^= (hash >> 6); 422 hash ^= (hash >> 6);
328 423
(...skipping 10 matching lines...) Expand all
339 } 434 }
340 #endif /* WITH_BIG_KEY */ 435 #endif /* WITH_BIG_KEY */
341 436
342 /* 437 /*
343 * xmlDictComputeFastKey: 438 * xmlDictComputeFastKey:
344 * 439 *
345 * Calculate a hash key using a fast hash function that works well 440 * Calculate a hash key using a fast hash function that works well
346 * for low hash table fill. 441 * for low hash table fill.
347 */ 442 */
348 static unsigned long 443 static unsigned long
349 xmlDictComputeFastKey(const xmlChar *name, int namelen) { 444 xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
350 unsigned long value = 0L; 445 unsigned long value = seed;
351 446
352 if (name == NULL) return(0); 447 if (name == NULL) return(0);
353 value = *name; 448 value = *name;
354 value <<= 5; 449 value <<= 5;
355 if (namelen > 10) { 450 if (namelen > 10) {
356 value += name[namelen - 1]; 451 value += name[namelen - 1];
357 namelen = 10; 452 namelen = 10;
358 } 453 }
359 switch (namelen) { 454 switch (namelen) {
360 case 10: value += name[9]; 455 case 10: value += name[9];
(...skipping 13 matching lines...) Expand all
374 /* 469 /*
375 * xmlDictComputeFastQKey: 470 * xmlDictComputeFastQKey:
376 * 471 *
377 * Calculate a hash key for two strings using a fast hash function 472 * Calculate a hash key for two strings using a fast hash function
378 * that works well for low hash table fill. 473 * that works well for low hash table fill.
379 * 474 *
380 * Neither of the two strings must be NULL. 475 * Neither of the two strings must be NULL.
381 */ 476 */
382 static unsigned long 477 static unsigned long
383 xmlDictComputeFastQKey(const xmlChar *prefix, int plen, 478 xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
384 const xmlChar *name, int len) 479 const xmlChar *name, int len, int seed)
385 { 480 {
386 unsigned long value = 0L; 481 unsigned long value = (unsigned long) seed;
387 482
388 if (plen == 0) 483 if (plen == 0)
389 value += 30 * (unsigned long) ':'; 484 value += 30 * (unsigned long) ':';
390 else 485 else
391 value += 30 * (*prefix); 486 value += 30 * (*prefix);
392 487
393 if (len > 10) { 488 if (len > 10) {
394 value += name[len - (plen + 1 + 1)]; 489 value += name[len - (plen + 1 + 1)];
395 len = 10; 490 len = 10;
396 if (plen > 10) 491 if (plen > 10)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 * 530 *
436 * Create a new dictionary 531 * Create a new dictionary
437 * 532 *
438 * Returns the newly created dictionnary, or NULL if an error occured. 533 * Returns the newly created dictionnary, or NULL if an error occured.
439 */ 534 */
440 xmlDictPtr 535 xmlDictPtr
441 xmlDictCreate(void) { 536 xmlDictCreate(void) {
442 xmlDictPtr dict; 537 xmlDictPtr dict;
443 538
444 if (!xmlDictInitialized) 539 if (!xmlDictInitialized)
445 if (!xmlInitializeDict()) 540 if (!__xmlInitializeDict())
446 return(NULL); 541 return(NULL);
447 542
448 #ifdef DICT_DEBUG_PATTERNS 543 #ifdef DICT_DEBUG_PATTERNS
449 fprintf(stderr, "C"); 544 fprintf(stderr, "C");
450 #endif 545 #endif
451 546
452 dict = xmlMalloc(sizeof(xmlDict)); 547 dict = xmlMalloc(sizeof(xmlDict));
453 if (dict) { 548 if (dict) {
454 dict->ref_counter = 1; 549 dict->ref_counter = 1;
550 dict->limit = 0;
455 551
456 dict->size = MIN_DICT_SIZE; 552 dict->size = MIN_DICT_SIZE;
457 dict->nbElems = 0; 553 dict->nbElems = 0;
458 dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry)); 554 dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
459 dict->strings = NULL; 555 dict->strings = NULL;
460 dict->subdict = NULL; 556 dict->subdict = NULL;
461 if (dict->dict) { 557 if (dict->dict) {
462 memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); 558 memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
559 #ifdef DICT_RANDOMIZATION
560 dict->seed = __xmlRandom();
561 #else
562 dict->seed = 0;
563 #endif
463 return(dict); 564 return(dict);
464 } 565 }
465 xmlFree(dict); 566 xmlFree(dict);
466 } 567 }
467 return(NULL); 568 return(NULL);
468 } 569 }
469 570
470 /** 571 /**
471 * xmlDictCreateSub: 572 * xmlDictCreateSub:
472 * @sub: an existing dictionnary 573 * @sub: an existing dictionnary
473 * 574 *
474 * Create a new dictionary, inheriting strings from the read-only 575 * Create a new dictionary, inheriting strings from the read-only
475 * dictionnary @sub. On lookup, strings are first searched in the 576 * dictionnary @sub. On lookup, strings are first searched in the
476 * new dictionnary, then in @sub, and if not found are created in the 577 * new dictionnary, then in @sub, and if not found are created in the
477 * new dictionnary. 578 * new dictionnary.
478 * 579 *
479 * Returns the newly created dictionnary, or NULL if an error occured. 580 * Returns the newly created dictionnary, or NULL if an error occured.
480 */ 581 */
481 xmlDictPtr 582 xmlDictPtr
482 xmlDictCreateSub(xmlDictPtr sub) { 583 xmlDictCreateSub(xmlDictPtr sub) {
483 xmlDictPtr dict = xmlDictCreate(); 584 xmlDictPtr dict = xmlDictCreate();
484 585
485 if ((dict != NULL) && (sub != NULL)) { 586 if ((dict != NULL) && (sub != NULL)) {
486 #ifdef DICT_DEBUG_PATTERNS 587 #ifdef DICT_DEBUG_PATTERNS
487 fprintf(stderr, "R"); 588 fprintf(stderr, "R");
488 #endif 589 #endif
590 dict->seed = sub->seed;
489 dict->subdict = sub; 591 dict->subdict = sub;
490 xmlDictReference(dict->subdict); 592 xmlDictReference(dict->subdict);
491 } 593 }
492 return(dict); 594 return(dict);
493 } 595 }
494 596
495 /** 597 /**
496 * xmlDictReference: 598 * xmlDictReference:
497 * @dict: the dictionnary 599 * @dict: the dictionnary
498 * 600 *
499 * Increment the reference counter of a dictionary 601 * Increment the reference counter of a dictionary
500 * 602 *
501 * Returns 0 in case of success and -1 in case of error 603 * Returns 0 in case of success and -1 in case of error
502 */ 604 */
503 int 605 int
504 xmlDictReference(xmlDictPtr dict) { 606 xmlDictReference(xmlDictPtr dict) {
505 if (!xmlDictInitialized) 607 if (!xmlDictInitialized)
506 if (!xmlInitializeDict()) 608 if (!__xmlInitializeDict())
507 return(-1); 609 return(-1);
508 610
509 if (dict == NULL) return -1; 611 if (dict == NULL) return -1;
510 xmlRMutexLock(xmlDictMutex); 612 xmlRMutexLock(xmlDictMutex);
511 dict->ref_counter++; 613 dict->ref_counter++;
512 xmlRMutexUnlock(xmlDictMutex); 614 xmlRMutexUnlock(xmlDictMutex);
513 return(0); 615 return(0);
514 } 616 }
515 617
516 /** 618 /**
517 * xmlDictGrow: 619 * xmlDictGrow:
518 * @dict: the dictionnary 620 * @dict: the dictionnary
519 * @size: the new size of the dictionnary 621 * @size: the new size of the dictionnary
520 * 622 *
521 * resize the dictionnary 623 * resize the dictionnary
522 * 624 *
523 * Returns 0 in case of success, -1 in case of failure 625 * Returns 0 in case of success, -1 in case of failure
524 */ 626 */
525 static int 627 static int
526 xmlDictGrow(xmlDictPtr dict, int size) { 628 xmlDictGrow(xmlDictPtr dict, size_t size) {
527 unsigned long key, okey; 629 unsigned long key, okey;
528 int oldsize, i; 630 size_t oldsize, i;
529 xmlDictEntryPtr iter, next; 631 xmlDictEntryPtr iter, next;
530 struct _xmlDictEntry *olddict; 632 struct _xmlDictEntry *olddict;
531 #ifdef DEBUG_GROW 633 #ifdef DEBUG_GROW
532 unsigned long nbElem = 0; 634 unsigned long nbElem = 0;
533 #endif 635 #endif
534 int ret = 0; 636 int ret = 0;
535 int keep_keys = 1; 637 int keep_keys = 1;
536 638
537 if (dict == NULL) 639 if (dict == NULL)
538 return(-1); 640 return(-1);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 #endif 737 #endif
636 738
637 iter = next; 739 iter = next;
638 } 740 }
639 } 741 }
640 742
641 xmlFree(olddict); 743 xmlFree(olddict);
642 744
643 #ifdef DEBUG_GROW 745 #ifdef DEBUG_GROW
644 xmlGenericError(xmlGenericErrorContext, 746 xmlGenericError(xmlGenericErrorContext,
645 » "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); 747 » "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem);
646 #endif 748 #endif
647 749
648 return(ret); 750 return(ret);
649 } 751 }
650 752
651 /** 753 /**
652 * xmlDictFree: 754 * xmlDictFree:
653 * @dict: the dictionnary 755 * @dict: the dictionnary
654 * 756 *
655 * Free the hash @dict and its contents. The userdata is 757 * Free the hash @dict and its contents. The userdata is
656 * deallocated with @f if provided. 758 * deallocated with @f if provided.
657 */ 759 */
658 void 760 void
659 xmlDictFree(xmlDictPtr dict) { 761 xmlDictFree(xmlDictPtr dict) {
660 int i; 762 size_t i;
661 xmlDictEntryPtr iter; 763 xmlDictEntryPtr iter;
662 xmlDictEntryPtr next; 764 xmlDictEntryPtr next;
663 int inside_dict = 0; 765 int inside_dict = 0;
664 xmlDictStringsPtr pool, nextp; 766 xmlDictStringsPtr pool, nextp;
665 767
666 if (dict == NULL) 768 if (dict == NULL)
667 return; 769 return;
668 770
669 if (!xmlDictInitialized) 771 if (!xmlDictInitialized)
670 if (!xmlInitializeDict()) 772 if (!__xmlInitializeDict())
671 return; 773 return;
672 774
673 /* decrement the counter, it may be shared by a parser and docs */ 775 /* decrement the counter, it may be shared by a parser and docs */
674 xmlRMutexLock(xmlDictMutex); 776 xmlRMutexLock(xmlDictMutex);
675 dict->ref_counter--; 777 dict->ref_counter--;
676 if (dict->ref_counter > 0) { 778 if (dict->ref_counter > 0) {
677 xmlRMutexUnlock(xmlDictMutex); 779 xmlRMutexUnlock(xmlDictMutex);
678 return; 780 return;
679 } 781 }
680 782
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 * Add the @name to the dictionnary @dict if not present. 821 * Add the @name to the dictionnary @dict if not present.
720 * 822 *
721 * Returns the internal copy of the name or NULL in case of internal error 823 * Returns the internal copy of the name or NULL in case of internal error
722 */ 824 */
723 const xmlChar * 825 const xmlChar *
724 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { 826 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
725 unsigned long key, okey, nbi = 0; 827 unsigned long key, okey, nbi = 0;
726 xmlDictEntryPtr entry; 828 xmlDictEntryPtr entry;
727 xmlDictEntryPtr insert; 829 xmlDictEntryPtr insert;
728 const xmlChar *ret; 830 const xmlChar *ret;
831 unsigned int l;
729 832
730 if ((dict == NULL) || (name == NULL)) 833 if ((dict == NULL) || (name == NULL))
731 return(NULL); 834 return(NULL);
732 835
733 if (len < 0) 836 if (len < 0)
734 len = strlen((const char *) name); 837 l = strlen((const char *) name);
838 else
839 l = len;
840
841 if (((dict->limit > 0) && (l >= dict->limit)) ||
842 (l > INT_MAX / 2))
843 return(NULL);
735 844
736 /* 845 /*
737 * Check for duplicate and insertion location. 846 * Check for duplicate and insertion location.
738 */ 847 */
739 okey = xmlDictComputeKey(dict, name, len); 848 okey = xmlDictComputeKey(dict, name, l);
740 key = okey % dict->size; 849 key = okey % dict->size;
741 if (dict->dict[key].valid == 0) { 850 if (dict->dict[key].valid == 0) {
742 insert = NULL; 851 insert = NULL;
743 } else { 852 } else {
744 for (insert = &(dict->dict[key]); insert->next != NULL; 853 for (insert = &(dict->dict[key]); insert->next != NULL;
745 insert = insert->next) { 854 insert = insert->next) {
746 #ifdef __GNUC__ 855 #ifdef __GNUC__
747 » if ((insert->okey == okey) && (insert->len == len)) { 856 » if ((insert->okey == okey) && (insert->len == l)) {
748 » » if (!memcmp(insert->name, name, len)) 857 » » if (!memcmp(insert->name, name, l))
749 return(insert->name); 858 return(insert->name);
750 } 859 }
751 #else 860 #else
752 » if ((insert->okey == okey) && (insert->len == len) && 861 » if ((insert->okey == okey) && (insert->len == l) &&
753 » (!xmlStrncmp(insert->name, name, len))) 862 » (!xmlStrncmp(insert->name, name, l)))
754 return(insert->name); 863 return(insert->name);
755 #endif 864 #endif
756 nbi++; 865 nbi++;
757 } 866 }
758 #ifdef __GNUC__ 867 #ifdef __GNUC__
759 » if ((insert->okey == okey) && (insert->len == len)) { 868 » if ((insert->okey == okey) && (insert->len == l)) {
760 » if (!memcmp(insert->name, name, len)) 869 » if (!memcmp(insert->name, name, l))
761 return(insert->name); 870 return(insert->name);
762 } 871 }
763 #else 872 #else
764 » if ((insert->okey == okey) && (insert->len == len) && 873 » if ((insert->okey == okey) && (insert->len == l) &&
765 » (!xmlStrncmp(insert->name, name, len))) 874 » (!xmlStrncmp(insert->name, name, l)))
766 return(insert->name); 875 return(insert->name);
767 #endif 876 #endif
768 } 877 }
769 878
770 if (dict->subdict) { 879 if (dict->subdict) {
771 unsigned long skey; 880 unsigned long skey;
772 881
773 /* we cannot always reuse the same okey for the subdict */ 882 /* we cannot always reuse the same okey for the subdict */
774 if (((dict->size == MIN_DICT_SIZE) && 883 if (((dict->size == MIN_DICT_SIZE) &&
775 (dict->subdict->size != MIN_DICT_SIZE)) || 884 (dict->subdict->size != MIN_DICT_SIZE)) ||
776 ((dict->size != MIN_DICT_SIZE) && 885 ((dict->size != MIN_DICT_SIZE) &&
777 (dict->subdict->size == MIN_DICT_SIZE))) 886 (dict->subdict->size == MIN_DICT_SIZE)))
778 » skey = xmlDictComputeKey(dict->subdict, name, len); 887 » skey = xmlDictComputeKey(dict->subdict, name, l);
779 else 888 else
780 skey = okey; 889 skey = okey;
781 890
782 key = skey % dict->subdict->size; 891 key = skey % dict->subdict->size;
783 if (dict->subdict->dict[key].valid != 0) { 892 if (dict->subdict->dict[key].valid != 0) {
784 xmlDictEntryPtr tmp; 893 xmlDictEntryPtr tmp;
785 894
786 for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; 895 for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
787 tmp = tmp->next) { 896 tmp = tmp->next) {
788 #ifdef __GNUC__ 897 #ifdef __GNUC__
789 » » if ((tmp->okey == skey) && (tmp->len == len)) { 898 » » if ((tmp->okey == skey) && (tmp->len == l)) {
790 » » if (!memcmp(tmp->name, name, len)) 899 » » if (!memcmp(tmp->name, name, l))
791 return(tmp->name); 900 return(tmp->name);
792 } 901 }
793 #else 902 #else
794 » » if ((tmp->okey == skey) && (tmp->len == len) && 903 » » if ((tmp->okey == skey) && (tmp->len == l) &&
795 » » (!xmlStrncmp(tmp->name, name, len))) 904 » » (!xmlStrncmp(tmp->name, name, l)))
796 return(tmp->name); 905 return(tmp->name);
797 #endif 906 #endif
798 nbi++; 907 nbi++;
799 } 908 }
800 #ifdef __GNUC__ 909 #ifdef __GNUC__
801 » if ((tmp->okey == skey) && (tmp->len == len)) { 910 » if ((tmp->okey == skey) && (tmp->len == l)) {
802 » » if (!memcmp(tmp->name, name, len)) 911 » » if (!memcmp(tmp->name, name, l))
803 return(tmp->name); 912 return(tmp->name);
804 } 913 }
805 #else 914 #else
806 » if ((tmp->okey == skey) && (tmp->len == len) && 915 » if ((tmp->okey == skey) && (tmp->len == l) &&
807 » » (!xmlStrncmp(tmp->name, name, len))) 916 » » (!xmlStrncmp(tmp->name, name, l)))
808 return(tmp->name); 917 return(tmp->name);
809 #endif 918 #endif
810 } 919 }
811 key = okey % dict->size; 920 key = okey % dict->size;
812 } 921 }
813 922
814 ret = xmlDictAddString(dict, name, len); 923 ret = xmlDictAddString(dict, name, l);
815 if (ret == NULL) 924 if (ret == NULL)
816 return(NULL); 925 return(NULL);
817 if (insert == NULL) { 926 if (insert == NULL) {
818 entry = &(dict->dict[key]); 927 entry = &(dict->dict[key]);
819 } else { 928 } else {
820 entry = xmlMalloc(sizeof(xmlDictEntry)); 929 entry = xmlMalloc(sizeof(xmlDictEntry));
821 if (entry == NULL) 930 if (entry == NULL)
822 return(NULL); 931 return(NULL);
823 } 932 }
824 entry->name = ret; 933 entry->name = ret;
825 entry->len = len; 934 entry->len = l;
826 entry->next = NULL; 935 entry->next = NULL;
827 entry->valid = 1; 936 entry->valid = 1;
828 entry->okey = okey; 937 entry->okey = okey;
829 938
830 939
831 if (insert != NULL) 940 if (insert != NULL)
832 insert->next = entry; 941 insert->next = entry;
833 942
834 dict->nbElems++; 943 dict->nbElems++;
835 944
836 if ((nbi > MAX_HASH_LEN) && 945 if ((nbi > MAX_HASH_LEN) &&
837 (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) { 946 (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
838 if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0) 947 if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
839 return(NULL); 948 return(NULL);
840 } 949 }
841 /* Note that entry may have been freed at this point by xmlDictGrow */ 950 /* Note that entry may have been freed at this point by xmlDictGrow */
842 951
843 return(ret); 952 return(ret);
844 } 953 }
845 954
846 /** 955 /**
847 * xmlDictExists: 956 * xmlDictExists:
848 * @dict: the dictionnary 957 * @dict: the dictionnary
849 * @name: the name of the userdata 958 * @name: the name of the userdata
850 * @len: the length of the name, if -1 it is recomputed 959 * @len: the length of the name, if -1 it is recomputed
851 * 960 *
852 * Check if the @name exists in the dictionnary @dict. 961 * Check if the @name exists in the dictionnary @dict.
853 * 962 *
854 * Returns the internal copy of the name or NULL if not found. 963 * Returns the internal copy of the name or NULL if not found.
855 */ 964 */
856 const xmlChar * 965 const xmlChar *
857 xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { 966 xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
858 unsigned long key, okey, nbi = 0; 967 unsigned long key, okey, nbi = 0;
859 xmlDictEntryPtr insert; 968 xmlDictEntryPtr insert;
969 unsigned int l;
860 970
861 if ((dict == NULL) || (name == NULL)) 971 if ((dict == NULL) || (name == NULL))
862 return(NULL); 972 return(NULL);
863 973
864 if (len < 0) 974 if (len < 0)
865 len = strlen((const char *) name); 975 l = strlen((const char *) name);
976 else
977 l = len;
978 if (((dict->limit > 0) && (l >= dict->limit)) ||
979 (l > INT_MAX / 2))
980 return(NULL);
866 981
867 /* 982 /*
868 * Check for duplicate and insertion location. 983 * Check for duplicate and insertion location.
869 */ 984 */
870 okey = xmlDictComputeKey(dict, name, len); 985 okey = xmlDictComputeKey(dict, name, l);
871 key = okey % dict->size; 986 key = okey % dict->size;
872 if (dict->dict[key].valid == 0) { 987 if (dict->dict[key].valid == 0) {
873 insert = NULL; 988 insert = NULL;
874 } else { 989 } else {
875 for (insert = &(dict->dict[key]); insert->next != NULL; 990 for (insert = &(dict->dict[key]); insert->next != NULL;
876 insert = insert->next) { 991 insert = insert->next) {
877 #ifdef __GNUC__ 992 #ifdef __GNUC__
878 » if ((insert->okey == okey) && (insert->len == len)) { 993 » if ((insert->okey == okey) && (insert->len == l)) {
879 » » if (!memcmp(insert->name, name, len)) 994 » » if (!memcmp(insert->name, name, l))
880 return(insert->name); 995 return(insert->name);
881 } 996 }
882 #else 997 #else
883 » if ((insert->okey == okey) && (insert->len == len) && 998 » if ((insert->okey == okey) && (insert->len == l) &&
884 » (!xmlStrncmp(insert->name, name, len))) 999 » (!xmlStrncmp(insert->name, name, l)))
885 return(insert->name); 1000 return(insert->name);
886 #endif 1001 #endif
887 nbi++; 1002 nbi++;
888 } 1003 }
889 #ifdef __GNUC__ 1004 #ifdef __GNUC__
890 » if ((insert->okey == okey) && (insert->len == len)) { 1005 » if ((insert->okey == okey) && (insert->len == l)) {
891 » if (!memcmp(insert->name, name, len)) 1006 » if (!memcmp(insert->name, name, l))
892 return(insert->name); 1007 return(insert->name);
893 } 1008 }
894 #else 1009 #else
895 » if ((insert->okey == okey) && (insert->len == len) && 1010 » if ((insert->okey == okey) && (insert->len == l) &&
896 » (!xmlStrncmp(insert->name, name, len))) 1011 » (!xmlStrncmp(insert->name, name, l)))
897 return(insert->name); 1012 return(insert->name);
898 #endif 1013 #endif
899 } 1014 }
900 1015
901 if (dict->subdict) { 1016 if (dict->subdict) {
902 unsigned long skey; 1017 unsigned long skey;
903 1018
904 /* we cannot always reuse the same okey for the subdict */ 1019 /* we cannot always reuse the same okey for the subdict */
905 if (((dict->size == MIN_DICT_SIZE) && 1020 if (((dict->size == MIN_DICT_SIZE) &&
906 (dict->subdict->size != MIN_DICT_SIZE)) || 1021 (dict->subdict->size != MIN_DICT_SIZE)) ||
907 ((dict->size != MIN_DICT_SIZE) && 1022 ((dict->size != MIN_DICT_SIZE) &&
908 (dict->subdict->size == MIN_DICT_SIZE))) 1023 (dict->subdict->size == MIN_DICT_SIZE)))
909 » skey = xmlDictComputeKey(dict->subdict, name, len); 1024 » skey = xmlDictComputeKey(dict->subdict, name, l);
910 else 1025 else
911 skey = okey; 1026 skey = okey;
912 1027
913 key = skey % dict->subdict->size; 1028 key = skey % dict->subdict->size;
914 if (dict->subdict->dict[key].valid != 0) { 1029 if (dict->subdict->dict[key].valid != 0) {
915 xmlDictEntryPtr tmp; 1030 xmlDictEntryPtr tmp;
916 1031
917 for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; 1032 for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
918 tmp = tmp->next) { 1033 tmp = tmp->next) {
919 #ifdef __GNUC__ 1034 #ifdef __GNUC__
920 » » if ((tmp->okey == skey) && (tmp->len == len)) { 1035 » » if ((tmp->okey == skey) && (tmp->len == l)) {
921 » » if (!memcmp(tmp->name, name, len)) 1036 » » if (!memcmp(tmp->name, name, l))
922 return(tmp->name); 1037 return(tmp->name);
923 } 1038 }
924 #else 1039 #else
925 » » if ((tmp->okey == skey) && (tmp->len == len) && 1040 » » if ((tmp->okey == skey) && (tmp->len == l) &&
926 » » (!xmlStrncmp(tmp->name, name, len))) 1041 » » (!xmlStrncmp(tmp->name, name, l)))
927 return(tmp->name); 1042 return(tmp->name);
928 #endif 1043 #endif
929 nbi++; 1044 nbi++;
930 } 1045 }
931 #ifdef __GNUC__ 1046 #ifdef __GNUC__
932 » if ((tmp->okey == skey) && (tmp->len == len)) { 1047 » if ((tmp->okey == skey) && (tmp->len == l)) {
933 » » if (!memcmp(tmp->name, name, len)) 1048 » » if (!memcmp(tmp->name, name, l))
934 return(tmp->name); 1049 return(tmp->name);
935 } 1050 }
936 #else 1051 #else
937 » if ((tmp->okey == skey) && (tmp->len == len) && 1052 » if ((tmp->okey == skey) && (tmp->len == l) &&
938 » » (!xmlStrncmp(tmp->name, name, len))) 1053 » » (!xmlStrncmp(tmp->name, name, l)))
939 return(tmp->name); 1054 return(tmp->name);
940 #endif 1055 #endif
941 } 1056 }
942 } 1057 }
943 1058
944 /* not found */ 1059 /* not found */
945 return(NULL); 1060 return(NULL);
946 } 1061 }
947 1062
948 /** 1063 /**
949 * xmlDictQLookup: 1064 * xmlDictQLookup:
950 * @dict: the dictionnary 1065 * @dict: the dictionnary
951 * @prefix: the prefix 1066 * @prefix: the prefix
952 * @name: the name 1067 * @name: the name
953 * 1068 *
954 * Add the QName @prefix:@name to the hash @dict if not present. 1069 * Add the QName @prefix:@name to the hash @dict if not present.
955 * 1070 *
956 * Returns the internal copy of the QName or NULL in case of internal error 1071 * Returns the internal copy of the QName or NULL in case of internal error
957 */ 1072 */
958 const xmlChar * 1073 const xmlChar *
959 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { 1074 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
960 unsigned long okey, key, nbi = 0; 1075 unsigned long okey, key, nbi = 0;
961 xmlDictEntryPtr entry; 1076 xmlDictEntryPtr entry;
962 xmlDictEntryPtr insert; 1077 xmlDictEntryPtr insert;
963 const xmlChar *ret; 1078 const xmlChar *ret;
964 int len, plen, l; 1079 unsigned int len, plen, l;
965 1080
966 if ((dict == NULL) || (name == NULL)) 1081 if ((dict == NULL) || (name == NULL))
967 return(NULL); 1082 return(NULL);
968 if (prefix == NULL) 1083 if (prefix == NULL)
969 return(xmlDictLookup(dict, name, -1)); 1084 return(xmlDictLookup(dict, name, -1));
970 1085
971 l = len = strlen((const char *) name); 1086 l = len = strlen((const char *) name);
972 plen = strlen((const char *) prefix); 1087 plen = strlen((const char *) prefix);
973 len += 1 + plen; 1088 len += 1 + plen;
974 1089
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 entry = xmlMalloc(sizeof(xmlDictEntry)); 1145 entry = xmlMalloc(sizeof(xmlDictEntry));
1031 if (entry == NULL) 1146 if (entry == NULL)
1032 return(NULL); 1147 return(NULL);
1033 } 1148 }
1034 entry->name = ret; 1149 entry->name = ret;
1035 entry->len = len; 1150 entry->len = len;
1036 entry->next = NULL; 1151 entry->next = NULL;
1037 entry->valid = 1; 1152 entry->valid = 1;
1038 entry->okey = okey; 1153 entry->okey = okey;
1039 1154
1040 if (insert != NULL) 1155 if (insert != NULL)
1041 insert->next = entry; 1156 insert->next = entry;
1042 1157
1043 dict->nbElems++; 1158 dict->nbElems++;
1044 1159
1045 if ((nbi > MAX_HASH_LEN) && 1160 if ((nbi > MAX_HASH_LEN) &&
1046 (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) 1161 (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
1047 xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size); 1162 xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
1048 /* Note that entry may have been freed at this point by xmlDictGrow */ 1163 /* Note that entry may have been freed at this point by xmlDictGrow */
1049 1164
1050 return(ret); 1165 return(ret);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 */ 1203 */
1089 int 1204 int
1090 xmlDictSize(xmlDictPtr dict) { 1205 xmlDictSize(xmlDictPtr dict) {
1091 if (dict == NULL) 1206 if (dict == NULL)
1092 return(-1); 1207 return(-1);
1093 if (dict->subdict) 1208 if (dict->subdict)
1094 return(dict->nbElems + dict->subdict->nbElems); 1209 return(dict->nbElems + dict->subdict->nbElems);
1095 return(dict->nbElems); 1210 return(dict->nbElems);
1096 } 1211 }
1097 1212
1213 /**
1214 * xmlDictSetLimit:
1215 * @dict: the dictionnary
1216 * @limit: the limit in bytes
1217 *
1218 * Set a size limit for the dictionary
1219 * Added in 2.9.0
1220 *
1221 * Returns the previous limit of the dictionary or 0
1222 */
1223 size_t
1224 xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
1225 size_t ret;
1226
1227 if (dict == NULL)
1228 return(0);
1229 ret = dict->limit;
1230 dict->limit = limit;
1231 return(ret);
1232 }
1233
1234 /**
1235 * xmlDictGetUsage:
1236 * @dict: the dictionnary
1237 *
1238 * Get how much memory is used by a dictionary for strings
1239 * Added in 2.9.0
1240 *
1241 * Returns the amount of strings allocated
1242 */
1243 size_t
1244 xmlDictGetUsage(xmlDictPtr dict) {
1245 xmlDictStringsPtr pool;
1246 size_t limit = 0;
1247
1248 if (dict == NULL)
1249 return(0);
1250 pool = dict->strings;
1251 while (pool != NULL) {
1252 limit += pool->size;
1253 pool = pool->next;
1254 }
1255 return(limit);
1256 }
1098 1257
1099 #define bottom_dict 1258 #define bottom_dict
1100 #include "elfgcchack.h" 1259 #include "elfgcchack.h"
OLDNEW
« no previous file with comments | « third_party/libxml/src/depcomp ('k') | third_party/libxml/src/elfgcchack.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698