@helm2/poc_jenki_rce 0.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of @helm2/poc_jenki_rce might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +118 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,1298 @@
1
+ /*
2
+ * dict.c: dictionary of reusable strings, just used to avoid allocation
3
+ * and freeing operations.
4
+ *
5
+ * Copyright (C) 2003-2012 Daniel Veillard.
6
+ *
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
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14
+ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15
+ *
16
+ * Author: daniel@veillard.com
17
+ */
18
+
19
+ #define IN_LIBXML
20
+ #include "libxml.h"
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
+ !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
43
+ #define DICT_RANDOMIZATION
44
+ #endif
45
+
46
+ #include <string.h>
47
+ #ifdef HAVE_STDINT_H
48
+ #include <stdint.h>
49
+ #else
50
+ #ifdef HAVE_INTTYPES_H
51
+ #include <inttypes.h>
52
+ #elif defined(_WIN32)
53
+ typedef unsigned __int32 uint32_t;
54
+ #endif
55
+ #endif
56
+ #include <libxml/tree.h>
57
+ #include <libxml/dict.h>
58
+ #include <libxml/xmlmemory.h>
59
+ #include <libxml/xmlerror.h>
60
+ #include <libxml/globals.h>
61
+
62
+ /* #define DEBUG_GROW */
63
+ /* #define DICT_DEBUG_PATTERNS */
64
+
65
+ #define MAX_HASH_LEN 3
66
+ #define MIN_DICT_SIZE 128
67
+ #define MAX_DICT_HASH 8 * 2048
68
+ #define WITH_BIG_KEY
69
+
70
+ #ifdef WITH_BIG_KEY
71
+ #define xmlDictComputeKey(dict, name, len) \
72
+ (((dict)->size == MIN_DICT_SIZE) ? \
73
+ xmlDictComputeFastKey(name, len, (dict)->seed) : \
74
+ xmlDictComputeBigKey(name, len, (dict)->seed))
75
+
76
+ #define xmlDictComputeQKey(dict, prefix, plen, name, len) \
77
+ (((prefix) == NULL) ? \
78
+ (xmlDictComputeKey(dict, name, len)) : \
79
+ (((dict)->size == MIN_DICT_SIZE) ? \
80
+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \
81
+ xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed)))
82
+
83
+ #else /* !WITH_BIG_KEY */
84
+ #define xmlDictComputeKey(dict, name, len) \
85
+ xmlDictComputeFastKey(name, len, (dict)->seed)
86
+ #define xmlDictComputeQKey(dict, prefix, plen, name, len) \
87
+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed)
88
+ #endif /* WITH_BIG_KEY */
89
+
90
+ /*
91
+ * An entry in the dictionary
92
+ */
93
+ typedef struct _xmlDictEntry xmlDictEntry;
94
+ typedef xmlDictEntry *xmlDictEntryPtr;
95
+ struct _xmlDictEntry {
96
+ struct _xmlDictEntry *next;
97
+ const xmlChar *name;
98
+ unsigned int len;
99
+ int valid;
100
+ unsigned long okey;
101
+ };
102
+
103
+ typedef struct _xmlDictStrings xmlDictStrings;
104
+ typedef xmlDictStrings *xmlDictStringsPtr;
105
+ struct _xmlDictStrings {
106
+ xmlDictStringsPtr next;
107
+ xmlChar *free;
108
+ xmlChar *end;
109
+ size_t size;
110
+ size_t nbStrings;
111
+ xmlChar array[1];
112
+ };
113
+ /*
114
+ * The entire dictionary
115
+ */
116
+ struct _xmlDict {
117
+ int ref_counter;
118
+
119
+ struct _xmlDictEntry *dict;
120
+ size_t size;
121
+ unsigned int nbElems;
122
+ xmlDictStringsPtr strings;
123
+
124
+ struct _xmlDict *subdict;
125
+ /* used for randomization */
126
+ int seed;
127
+ /* used to impose a limit on size */
128
+ size_t limit;
129
+ };
130
+
131
+ /*
132
+ * A mutex for modifying the reference counter for shared
133
+ * dictionaries.
134
+ */
135
+ static xmlRMutexPtr xmlDictMutex = NULL;
136
+
137
+ /*
138
+ * Whether the dictionary mutex was initialized.
139
+ */
140
+ static int xmlDictInitialized = 0;
141
+
142
+ #ifdef DICT_RANDOMIZATION
143
+ #ifdef HAVE_RAND_R
144
+ /*
145
+ * Internal data for random function, protected by xmlDictMutex
146
+ */
147
+ static unsigned int rand_seed = 0;
148
+ #endif
149
+ #endif
150
+
151
+ /**
152
+ * xmlInitializeDict:
153
+ *
154
+ * Do the dictionary mutex initialization.
155
+ * this function is deprecated
156
+ *
157
+ * Returns 0 if initialization was already done, and 1 if that
158
+ * call led to the initialization
159
+ */
160
+ int xmlInitializeDict(void) {
161
+ return(0);
162
+ }
163
+
164
+ /**
165
+ * __xmlInitializeDict:
166
+ *
167
+ * This function is not public
168
+ * Do the dictionary mutex initialization.
169
+ * this function is not thread safe, initialization should
170
+ * normally be done once at setup when called from xmlOnceInit()
171
+ * we may also land in this code if thread support is not compiled in
172
+ *
173
+ * Returns 0 if initialization was already done, and 1 if that
174
+ * call led to the initialization
175
+ */
176
+ int __xmlInitializeDict(void) {
177
+ if (xmlDictInitialized)
178
+ return(1);
179
+
180
+ if ((xmlDictMutex = xmlNewRMutex()) == NULL)
181
+ return(0);
182
+ xmlRMutexLock(xmlDictMutex);
183
+
184
+ #ifdef DICT_RANDOMIZATION
185
+ #ifdef HAVE_RAND_R
186
+ rand_seed = time(NULL);
187
+ rand_r(& rand_seed);
188
+ #else
189
+ srand(time(NULL));
190
+ #endif
191
+ #endif
192
+ xmlDictInitialized = 1;
193
+ xmlRMutexUnlock(xmlDictMutex);
194
+ return(1);
195
+ }
196
+
197
+ #ifdef DICT_RANDOMIZATION
198
+ int __xmlRandom(void) {
199
+ int ret;
200
+
201
+ if (xmlDictInitialized == 0)
202
+ __xmlInitializeDict();
203
+
204
+ xmlRMutexLock(xmlDictMutex);
205
+ #ifdef HAVE_RAND_R
206
+ ret = rand_r(& rand_seed);
207
+ #else
208
+ ret = rand();
209
+ #endif
210
+ xmlRMutexUnlock(xmlDictMutex);
211
+ return(ret);
212
+ }
213
+ #endif
214
+
215
+ /**
216
+ * xmlDictCleanup:
217
+ *
218
+ * Free the dictionary mutex. Do not call unless sure the library
219
+ * is not in use anymore !
220
+ */
221
+ void
222
+ xmlDictCleanup(void) {
223
+ if (!xmlDictInitialized)
224
+ return;
225
+
226
+ xmlFreeRMutex(xmlDictMutex);
227
+
228
+ xmlDictInitialized = 0;
229
+ }
230
+
231
+ /*
232
+ * xmlDictAddString:
233
+ * @dict: the dictionary
234
+ * @name: the name of the userdata
235
+ * @len: the length of the name
236
+ *
237
+ * Add the string to the array[s]
238
+ *
239
+ * Returns the pointer of the local string, or NULL in case of error.
240
+ */
241
+ static const xmlChar *
242
+ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) {
243
+ xmlDictStringsPtr pool;
244
+ const xmlChar *ret;
245
+ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
246
+ size_t limit = 0;
247
+
248
+ #ifdef DICT_DEBUG_PATTERNS
249
+ fprintf(stderr, "-");
250
+ #endif
251
+ pool = dict->strings;
252
+ while (pool != NULL) {
253
+ if ((size_t)(pool->end - pool->free) > namelen)
254
+ goto found_pool;
255
+ if (pool->size > size) size = pool->size;
256
+ limit += pool->size;
257
+ pool = pool->next;
258
+ }
259
+ /*
260
+ * Not found, need to allocate
261
+ */
262
+ if (pool == NULL) {
263
+ if ((dict->limit > 0) && (limit > dict->limit)) {
264
+ return(NULL);
265
+ }
266
+
267
+ if (size == 0) size = 1000;
268
+ else size *= 4; /* exponential growth */
269
+ if (size < 4 * namelen)
270
+ size = 4 * namelen; /* just in case ! */
271
+ pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
272
+ if (pool == NULL)
273
+ return(NULL);
274
+ pool->size = size;
275
+ pool->nbStrings = 0;
276
+ pool->free = &pool->array[0];
277
+ pool->end = &pool->array[size];
278
+ pool->next = dict->strings;
279
+ dict->strings = pool;
280
+ #ifdef DICT_DEBUG_PATTERNS
281
+ fprintf(stderr, "+");
282
+ #endif
283
+ }
284
+ found_pool:
285
+ ret = pool->free;
286
+ memcpy(pool->free, name, namelen);
287
+ pool->free += namelen;
288
+ *(pool->free++) = 0;
289
+ pool->nbStrings++;
290
+ return(ret);
291
+ }
292
+
293
+ /*
294
+ * xmlDictAddQString:
295
+ * @dict: the dictionary
296
+ * @prefix: the prefix of the userdata
297
+ * @plen: the prefix length
298
+ * @name: the name of the userdata
299
+ * @len: the length of the name
300
+ *
301
+ * Add the QName to the array[s]
302
+ *
303
+ * Returns the pointer of the local string, or NULL in case of error.
304
+ */
305
+ static const xmlChar *
306
+ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen,
307
+ const xmlChar *name, unsigned int namelen)
308
+ {
309
+ xmlDictStringsPtr pool;
310
+ const xmlChar *ret;
311
+ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
312
+ size_t limit = 0;
313
+
314
+ if (prefix == NULL) return(xmlDictAddString(dict, name, namelen));
315
+
316
+ #ifdef DICT_DEBUG_PATTERNS
317
+ fprintf(stderr, "=");
318
+ #endif
319
+ pool = dict->strings;
320
+ while (pool != NULL) {
321
+ if ((size_t)(pool->end - pool->free) > namelen + plen + 1)
322
+ goto found_pool;
323
+ if (pool->size > size) size = pool->size;
324
+ limit += pool->size;
325
+ pool = pool->next;
326
+ }
327
+ /*
328
+ * Not found, need to allocate
329
+ */
330
+ if (pool == NULL) {
331
+ if ((dict->limit > 0) && (limit > dict->limit)) {
332
+ return(NULL);
333
+ }
334
+
335
+ if (size == 0) size = 1000;
336
+ else size *= 4; /* exponential growth */
337
+ if (size < 4 * (namelen + plen + 1))
338
+ size = 4 * (namelen + plen + 1); /* just in case ! */
339
+ pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
340
+ if (pool == NULL)
341
+ return(NULL);
342
+ pool->size = size;
343
+ pool->nbStrings = 0;
344
+ pool->free = &pool->array[0];
345
+ pool->end = &pool->array[size];
346
+ pool->next = dict->strings;
347
+ dict->strings = pool;
348
+ #ifdef DICT_DEBUG_PATTERNS
349
+ fprintf(stderr, "+");
350
+ #endif
351
+ }
352
+ found_pool:
353
+ ret = pool->free;
354
+ memcpy(pool->free, prefix, plen);
355
+ pool->free += plen;
356
+ *(pool->free++) = ':';
357
+ memcpy(pool->free, name, namelen);
358
+ pool->free += namelen;
359
+ *(pool->free++) = 0;
360
+ pool->nbStrings++;
361
+ return(ret);
362
+ }
363
+
364
+ #ifdef WITH_BIG_KEY
365
+ /*
366
+ * xmlDictComputeBigKey:
367
+ *
368
+ * Calculate a hash key using a good hash function that works well for
369
+ * larger hash table sizes.
370
+ *
371
+ * Hash function by "One-at-a-Time Hash" see
372
+ * http://burtleburtle.net/bob/hash/doobs.html
373
+ */
374
+
375
+ #ifdef __clang__
376
+ ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
377
+ #endif
378
+ static uint32_t
379
+ xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
380
+ uint32_t hash;
381
+ int i;
382
+
383
+ if (namelen <= 0 || data == NULL) return(0);
384
+
385
+ hash = seed;
386
+
387
+ for (i = 0;i < namelen; i++) {
388
+ hash += data[i];
389
+ hash += (hash << 10);
390
+ hash ^= (hash >> 6);
391
+ }
392
+ hash += (hash << 3);
393
+ hash ^= (hash >> 11);
394
+ hash += (hash << 15);
395
+
396
+ return hash;
397
+ }
398
+
399
+ /*
400
+ * xmlDictComputeBigQKey:
401
+ *
402
+ * Calculate a hash key for two strings using a good hash function
403
+ * that works well for larger hash table sizes.
404
+ *
405
+ * Hash function by "One-at-a-Time Hash" see
406
+ * http://burtleburtle.net/bob/hash/doobs.html
407
+ *
408
+ * Neither of the two strings must be NULL.
409
+ */
410
+ #ifdef __clang__
411
+ ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
412
+ #endif
413
+ static unsigned long
414
+ xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
415
+ const xmlChar *name, int len, int seed)
416
+ {
417
+ uint32_t hash;
418
+ int i;
419
+
420
+ hash = seed;
421
+
422
+ for (i = 0;i < plen; i++) {
423
+ hash += prefix[i];
424
+ hash += (hash << 10);
425
+ hash ^= (hash >> 6);
426
+ }
427
+ hash += ':';
428
+ hash += (hash << 10);
429
+ hash ^= (hash >> 6);
430
+
431
+ for (i = 0;i < len; i++) {
432
+ hash += name[i];
433
+ hash += (hash << 10);
434
+ hash ^= (hash >> 6);
435
+ }
436
+ hash += (hash << 3);
437
+ hash ^= (hash >> 11);
438
+ hash += (hash << 15);
439
+
440
+ return hash;
441
+ }
442
+ #endif /* WITH_BIG_KEY */
443
+
444
+ /*
445
+ * xmlDictComputeFastKey:
446
+ *
447
+ * Calculate a hash key using a fast hash function that works well
448
+ * for low hash table fill.
449
+ */
450
+ static unsigned long
451
+ xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
452
+ unsigned long value = seed;
453
+
454
+ if (name == NULL) return(0);
455
+ value += *name;
456
+ value <<= 5;
457
+ if (namelen > 10) {
458
+ value += name[namelen - 1];
459
+ namelen = 10;
460
+ }
461
+ switch (namelen) {
462
+ case 10: value += name[9];
463
+ /* Falls through. */
464
+ case 9: value += name[8];
465
+ /* Falls through. */
466
+ case 8: value += name[7];
467
+ /* Falls through. */
468
+ case 7: value += name[6];
469
+ /* Falls through. */
470
+ case 6: value += name[5];
471
+ /* Falls through. */
472
+ case 5: value += name[4];
473
+ /* Falls through. */
474
+ case 4: value += name[3];
475
+ /* Falls through. */
476
+ case 3: value += name[2];
477
+ /* Falls through. */
478
+ case 2: value += name[1];
479
+ /* Falls through. */
480
+ default: break;
481
+ }
482
+ return(value);
483
+ }
484
+
485
+ /*
486
+ * xmlDictComputeFastQKey:
487
+ *
488
+ * Calculate a hash key for two strings using a fast hash function
489
+ * that works well for low hash table fill.
490
+ *
491
+ * Neither of the two strings must be NULL.
492
+ */
493
+ static unsigned long
494
+ xmlDictComputeFastQKey(const xmlChar *prefix, int plen,
495
+ const xmlChar *name, int len, int seed)
496
+ {
497
+ unsigned long value = (unsigned long) seed;
498
+
499
+ if (plen == 0)
500
+ value += 30 * (unsigned long) ':';
501
+ else
502
+ value += 30 * (*prefix);
503
+
504
+ if (len > 10) {
505
+ int offset = len - (plen + 1 + 1);
506
+ if (offset < 0)
507
+ offset = len - (10 + 1);
508
+ value += name[offset];
509
+ len = 10;
510
+ if (plen > 10)
511
+ plen = 10;
512
+ }
513
+ switch (plen) {
514
+ case 10: value += prefix[9];
515
+ /* Falls through. */
516
+ case 9: value += prefix[8];
517
+ /* Falls through. */
518
+ case 8: value += prefix[7];
519
+ /* Falls through. */
520
+ case 7: value += prefix[6];
521
+ /* Falls through. */
522
+ case 6: value += prefix[5];
523
+ /* Falls through. */
524
+ case 5: value += prefix[4];
525
+ /* Falls through. */
526
+ case 4: value += prefix[3];
527
+ /* Falls through. */
528
+ case 3: value += prefix[2];
529
+ /* Falls through. */
530
+ case 2: value += prefix[1];
531
+ /* Falls through. */
532
+ case 1: value += prefix[0];
533
+ /* Falls through. */
534
+ default: break;
535
+ }
536
+ len -= plen;
537
+ if (len > 0) {
538
+ value += (unsigned long) ':';
539
+ len--;
540
+ }
541
+ switch (len) {
542
+ case 10: value += name[9];
543
+ /* Falls through. */
544
+ case 9: value += name[8];
545
+ /* Falls through. */
546
+ case 8: value += name[7];
547
+ /* Falls through. */
548
+ case 7: value += name[6];
549
+ /* Falls through. */
550
+ case 6: value += name[5];
551
+ /* Falls through. */
552
+ case 5: value += name[4];
553
+ /* Falls through. */
554
+ case 4: value += name[3];
555
+ /* Falls through. */
556
+ case 3: value += name[2];
557
+ /* Falls through. */
558
+ case 2: value += name[1];
559
+ /* Falls through. */
560
+ case 1: value += name[0];
561
+ /* Falls through. */
562
+ default: break;
563
+ }
564
+ return(value);
565
+ }
566
+
567
+ /**
568
+ * xmlDictCreate:
569
+ *
570
+ * Create a new dictionary
571
+ *
572
+ * Returns the newly created dictionary, or NULL if an error occurred.
573
+ */
574
+ xmlDictPtr
575
+ xmlDictCreate(void) {
576
+ xmlDictPtr dict;
577
+
578
+ if (!xmlDictInitialized)
579
+ if (!__xmlInitializeDict())
580
+ return(NULL);
581
+
582
+ #ifdef DICT_DEBUG_PATTERNS
583
+ fprintf(stderr, "C");
584
+ #endif
585
+
586
+ dict = xmlMalloc(sizeof(xmlDict));
587
+ if (dict) {
588
+ dict->ref_counter = 1;
589
+ dict->limit = 0;
590
+
591
+ dict->size = MIN_DICT_SIZE;
592
+ dict->nbElems = 0;
593
+ dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
594
+ dict->strings = NULL;
595
+ dict->subdict = NULL;
596
+ if (dict->dict) {
597
+ memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
598
+ #ifdef DICT_RANDOMIZATION
599
+ dict->seed = __xmlRandom();
600
+ #else
601
+ dict->seed = 0;
602
+ #endif
603
+ return(dict);
604
+ }
605
+ xmlFree(dict);
606
+ }
607
+ return(NULL);
608
+ }
609
+
610
+ /**
611
+ * xmlDictCreateSub:
612
+ * @sub: an existing dictionary
613
+ *
614
+ * Create a new dictionary, inheriting strings from the read-only
615
+ * dictionary @sub. On lookup, strings are first searched in the
616
+ * new dictionary, then in @sub, and if not found are created in the
617
+ * new dictionary.
618
+ *
619
+ * Returns the newly created dictionary, or NULL if an error occurred.
620
+ */
621
+ xmlDictPtr
622
+ xmlDictCreateSub(xmlDictPtr sub) {
623
+ xmlDictPtr dict = xmlDictCreate();
624
+
625
+ if ((dict != NULL) && (sub != NULL)) {
626
+ #ifdef DICT_DEBUG_PATTERNS
627
+ fprintf(stderr, "R");
628
+ #endif
629
+ dict->seed = sub->seed;
630
+ dict->subdict = sub;
631
+ xmlDictReference(dict->subdict);
632
+ }
633
+ return(dict);
634
+ }
635
+
636
+ /**
637
+ * xmlDictReference:
638
+ * @dict: the dictionary
639
+ *
640
+ * Increment the reference counter of a dictionary
641
+ *
642
+ * Returns 0 in case of success and -1 in case of error
643
+ */
644
+ int
645
+ xmlDictReference(xmlDictPtr dict) {
646
+ if (!xmlDictInitialized)
647
+ if (!__xmlInitializeDict())
648
+ return(-1);
649
+
650
+ if (dict == NULL) return -1;
651
+ xmlRMutexLock(xmlDictMutex);
652
+ dict->ref_counter++;
653
+ xmlRMutexUnlock(xmlDictMutex);
654
+ return(0);
655
+ }
656
+
657
+ /**
658
+ * xmlDictGrow:
659
+ * @dict: the dictionary
660
+ * @size: the new size of the dictionary
661
+ *
662
+ * resize the dictionary
663
+ *
664
+ * Returns 0 in case of success, -1 in case of failure
665
+ */
666
+ static int
667
+ xmlDictGrow(xmlDictPtr dict, size_t size) {
668
+ unsigned long key, okey;
669
+ size_t oldsize, i;
670
+ xmlDictEntryPtr iter, next;
671
+ struct _xmlDictEntry *olddict;
672
+ #ifdef DEBUG_GROW
673
+ unsigned long nbElem = 0;
674
+ #endif
675
+ int ret = 0;
676
+ int keep_keys = 1;
677
+
678
+ if (dict == NULL)
679
+ return(-1);
680
+ if (size < 8)
681
+ return(-1);
682
+ if (size > 8 * 2048)
683
+ return(-1);
684
+
685
+ #ifdef DICT_DEBUG_PATTERNS
686
+ fprintf(stderr, "*");
687
+ #endif
688
+
689
+ oldsize = dict->size;
690
+ olddict = dict->dict;
691
+ if (olddict == NULL)
692
+ return(-1);
693
+ if (oldsize == MIN_DICT_SIZE)
694
+ keep_keys = 0;
695
+
696
+ dict->dict = xmlMalloc(size * sizeof(xmlDictEntry));
697
+ if (dict->dict == NULL) {
698
+ dict->dict = olddict;
699
+ return(-1);
700
+ }
701
+ memset(dict->dict, 0, size * sizeof(xmlDictEntry));
702
+ dict->size = size;
703
+
704
+ /* If the two loops are merged, there would be situations where
705
+ a new entry needs to allocated and data copied into it from
706
+ the main dict. It is nicer to run through the array twice, first
707
+ copying all the elements in the main array (less probability of
708
+ allocate) and then the rest, so we only free in the second loop.
709
+ */
710
+ for (i = 0; i < oldsize; i++) {
711
+ if (olddict[i].valid == 0)
712
+ continue;
713
+
714
+ if (keep_keys)
715
+ okey = olddict[i].okey;
716
+ else
717
+ okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
718
+ key = okey % dict->size;
719
+
720
+ if (dict->dict[key].valid == 0) {
721
+ memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
722
+ dict->dict[key].next = NULL;
723
+ dict->dict[key].okey = okey;
724
+ } else {
725
+ xmlDictEntryPtr entry;
726
+
727
+ entry = xmlMalloc(sizeof(xmlDictEntry));
728
+ if (entry != NULL) {
729
+ entry->name = olddict[i].name;
730
+ entry->len = olddict[i].len;
731
+ entry->okey = okey;
732
+ entry->next = dict->dict[key].next;
733
+ entry->valid = 1;
734
+ dict->dict[key].next = entry;
735
+ } else {
736
+ /*
737
+ * we don't have much ways to alert from here
738
+ * result is losing an entry and unicity guarantee
739
+ */
740
+ ret = -1;
741
+ }
742
+ }
743
+ #ifdef DEBUG_GROW
744
+ nbElem++;
745
+ #endif
746
+ }
747
+
748
+ for (i = 0; i < oldsize; i++) {
749
+ iter = olddict[i].next;
750
+ while (iter) {
751
+ next = iter->next;
752
+
753
+ /*
754
+ * put back the entry in the new dict
755
+ */
756
+
757
+ if (keep_keys)
758
+ okey = iter->okey;
759
+ else
760
+ okey = xmlDictComputeKey(dict, iter->name, iter->len);
761
+ key = okey % dict->size;
762
+ if (dict->dict[key].valid == 0) {
763
+ memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
764
+ dict->dict[key].next = NULL;
765
+ dict->dict[key].valid = 1;
766
+ dict->dict[key].okey = okey;
767
+ xmlFree(iter);
768
+ } else {
769
+ iter->next = dict->dict[key].next;
770
+ iter->okey = okey;
771
+ dict->dict[key].next = iter;
772
+ }
773
+
774
+ #ifdef DEBUG_GROW
775
+ nbElem++;
776
+ #endif
777
+
778
+ iter = next;
779
+ }
780
+ }
781
+
782
+ xmlFree(olddict);
783
+
784
+ #ifdef DEBUG_GROW
785
+ xmlGenericError(xmlGenericErrorContext,
786
+ "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem);
787
+ #endif
788
+
789
+ return(ret);
790
+ }
791
+
792
+ /**
793
+ * xmlDictFree:
794
+ * @dict: the dictionary
795
+ *
796
+ * Free the hash @dict and its contents. The userdata is
797
+ * deallocated with @f if provided.
798
+ */
799
+ void
800
+ xmlDictFree(xmlDictPtr dict) {
801
+ size_t i;
802
+ xmlDictEntryPtr iter;
803
+ xmlDictEntryPtr next;
804
+ int inside_dict = 0;
805
+ xmlDictStringsPtr pool, nextp;
806
+
807
+ if (dict == NULL)
808
+ return;
809
+
810
+ if (!xmlDictInitialized)
811
+ if (!__xmlInitializeDict())
812
+ return;
813
+
814
+ /* decrement the counter, it may be shared by a parser and docs */
815
+ xmlRMutexLock(xmlDictMutex);
816
+ dict->ref_counter--;
817
+ if (dict->ref_counter > 0) {
818
+ xmlRMutexUnlock(xmlDictMutex);
819
+ return;
820
+ }
821
+
822
+ xmlRMutexUnlock(xmlDictMutex);
823
+
824
+ if (dict->subdict != NULL) {
825
+ xmlDictFree(dict->subdict);
826
+ }
827
+
828
+ if (dict->dict) {
829
+ for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
830
+ iter = &(dict->dict[i]);
831
+ if (iter->valid == 0)
832
+ continue;
833
+ inside_dict = 1;
834
+ while (iter) {
835
+ next = iter->next;
836
+ if (!inside_dict)
837
+ xmlFree(iter);
838
+ dict->nbElems--;
839
+ inside_dict = 0;
840
+ iter = next;
841
+ }
842
+ }
843
+ xmlFree(dict->dict);
844
+ }
845
+ pool = dict->strings;
846
+ while (pool != NULL) {
847
+ nextp = pool->next;
848
+ xmlFree(pool);
849
+ pool = nextp;
850
+ }
851
+ xmlFree(dict);
852
+ }
853
+
854
+ /**
855
+ * xmlDictLookup:
856
+ * @dict: the dictionary
857
+ * @name: the name of the userdata
858
+ * @len: the length of the name, if -1 it is recomputed
859
+ *
860
+ * Add the @name to the dictionary @dict if not present.
861
+ *
862
+ * Returns the internal copy of the name or NULL in case of internal error
863
+ */
864
+ const xmlChar *
865
+ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
866
+ unsigned long key, okey, nbi = 0;
867
+ xmlDictEntryPtr entry;
868
+ xmlDictEntryPtr insert;
869
+ const xmlChar *ret;
870
+ unsigned int l;
871
+
872
+ if ((dict == NULL) || (name == NULL))
873
+ return(NULL);
874
+
875
+ if (len < 0)
876
+ l = strlen((const char *) name);
877
+ else
878
+ l = len;
879
+
880
+ if (((dict->limit > 0) && (l >= dict->limit)) ||
881
+ (l > INT_MAX / 2))
882
+ return(NULL);
883
+
884
+ /*
885
+ * Check for duplicate and insertion location.
886
+ */
887
+ okey = xmlDictComputeKey(dict, name, l);
888
+ key = okey % dict->size;
889
+ if (dict->dict[key].valid == 0) {
890
+ insert = NULL;
891
+ } else {
892
+ for (insert = &(dict->dict[key]); insert->next != NULL;
893
+ insert = insert->next) {
894
+ #ifdef __GNUC__
895
+ if ((insert->okey == okey) && (insert->len == l)) {
896
+ if (!memcmp(insert->name, name, l))
897
+ return(insert->name);
898
+ }
899
+ #else
900
+ if ((insert->okey == okey) && (insert->len == l) &&
901
+ (!xmlStrncmp(insert->name, name, l)))
902
+ return(insert->name);
903
+ #endif
904
+ nbi++;
905
+ }
906
+ #ifdef __GNUC__
907
+ if ((insert->okey == okey) && (insert->len == l)) {
908
+ if (!memcmp(insert->name, name, l))
909
+ return(insert->name);
910
+ }
911
+ #else
912
+ if ((insert->okey == okey) && (insert->len == l) &&
913
+ (!xmlStrncmp(insert->name, name, l)))
914
+ return(insert->name);
915
+ #endif
916
+ }
917
+
918
+ if (dict->subdict) {
919
+ unsigned long skey;
920
+
921
+ /* we cannot always reuse the same okey for the subdict */
922
+ if (((dict->size == MIN_DICT_SIZE) &&
923
+ (dict->subdict->size != MIN_DICT_SIZE)) ||
924
+ ((dict->size != MIN_DICT_SIZE) &&
925
+ (dict->subdict->size == MIN_DICT_SIZE)))
926
+ skey = xmlDictComputeKey(dict->subdict, name, l);
927
+ else
928
+ skey = okey;
929
+
930
+ key = skey % dict->subdict->size;
931
+ if (dict->subdict->dict[key].valid != 0) {
932
+ xmlDictEntryPtr tmp;
933
+
934
+ for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
935
+ tmp = tmp->next) {
936
+ #ifdef __GNUC__
937
+ if ((tmp->okey == skey) && (tmp->len == l)) {
938
+ if (!memcmp(tmp->name, name, l))
939
+ return(tmp->name);
940
+ }
941
+ #else
942
+ if ((tmp->okey == skey) && (tmp->len == l) &&
943
+ (!xmlStrncmp(tmp->name, name, l)))
944
+ return(tmp->name);
945
+ #endif
946
+ nbi++;
947
+ }
948
+ #ifdef __GNUC__
949
+ if ((tmp->okey == skey) && (tmp->len == l)) {
950
+ if (!memcmp(tmp->name, name, l))
951
+ return(tmp->name);
952
+ }
953
+ #else
954
+ if ((tmp->okey == skey) && (tmp->len == l) &&
955
+ (!xmlStrncmp(tmp->name, name, l)))
956
+ return(tmp->name);
957
+ #endif
958
+ }
959
+ key = okey % dict->size;
960
+ }
961
+
962
+ ret = xmlDictAddString(dict, name, l);
963
+ if (ret == NULL)
964
+ return(NULL);
965
+ if (insert == NULL) {
966
+ entry = &(dict->dict[key]);
967
+ } else {
968
+ entry = xmlMalloc(sizeof(xmlDictEntry));
969
+ if (entry == NULL)
970
+ return(NULL);
971
+ }
972
+ entry->name = ret;
973
+ entry->len = l;
974
+ entry->next = NULL;
975
+ entry->valid = 1;
976
+ entry->okey = okey;
977
+
978
+
979
+ if (insert != NULL)
980
+ insert->next = entry;
981
+
982
+ dict->nbElems++;
983
+
984
+ if ((nbi > MAX_HASH_LEN) &&
985
+ (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) {
986
+ if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0)
987
+ return(NULL);
988
+ }
989
+ /* Note that entry may have been freed at this point by xmlDictGrow */
990
+
991
+ return(ret);
992
+ }
993
+
994
+ /**
995
+ * xmlDictExists:
996
+ * @dict: the dictionary
997
+ * @name: the name of the userdata
998
+ * @len: the length of the name, if -1 it is recomputed
999
+ *
1000
+ * Check if the @name exists in the dictionary @dict.
1001
+ *
1002
+ * Returns the internal copy of the name or NULL if not found.
1003
+ */
1004
+ const xmlChar *
1005
+ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) {
1006
+ unsigned long key, okey, nbi = 0;
1007
+ xmlDictEntryPtr insert;
1008
+ unsigned int l;
1009
+
1010
+ if ((dict == NULL) || (name == NULL))
1011
+ return(NULL);
1012
+
1013
+ if (len < 0)
1014
+ l = strlen((const char *) name);
1015
+ else
1016
+ l = len;
1017
+ if (((dict->limit > 0) && (l >= dict->limit)) ||
1018
+ (l > INT_MAX / 2))
1019
+ return(NULL);
1020
+
1021
+ /*
1022
+ * Check for duplicate and insertion location.
1023
+ */
1024
+ okey = xmlDictComputeKey(dict, name, l);
1025
+ key = okey % dict->size;
1026
+ if (dict->dict[key].valid == 0) {
1027
+ insert = NULL;
1028
+ } else {
1029
+ for (insert = &(dict->dict[key]); insert->next != NULL;
1030
+ insert = insert->next) {
1031
+ #ifdef __GNUC__
1032
+ if ((insert->okey == okey) && (insert->len == l)) {
1033
+ if (!memcmp(insert->name, name, l))
1034
+ return(insert->name);
1035
+ }
1036
+ #else
1037
+ if ((insert->okey == okey) && (insert->len == l) &&
1038
+ (!xmlStrncmp(insert->name, name, l)))
1039
+ return(insert->name);
1040
+ #endif
1041
+ nbi++;
1042
+ }
1043
+ #ifdef __GNUC__
1044
+ if ((insert->okey == okey) && (insert->len == l)) {
1045
+ if (!memcmp(insert->name, name, l))
1046
+ return(insert->name);
1047
+ }
1048
+ #else
1049
+ if ((insert->okey == okey) && (insert->len == l) &&
1050
+ (!xmlStrncmp(insert->name, name, l)))
1051
+ return(insert->name);
1052
+ #endif
1053
+ }
1054
+
1055
+ if (dict->subdict) {
1056
+ unsigned long skey;
1057
+
1058
+ /* we cannot always reuse the same okey for the subdict */
1059
+ if (((dict->size == MIN_DICT_SIZE) &&
1060
+ (dict->subdict->size != MIN_DICT_SIZE)) ||
1061
+ ((dict->size != MIN_DICT_SIZE) &&
1062
+ (dict->subdict->size == MIN_DICT_SIZE)))
1063
+ skey = xmlDictComputeKey(dict->subdict, name, l);
1064
+ else
1065
+ skey = okey;
1066
+
1067
+ key = skey % dict->subdict->size;
1068
+ if (dict->subdict->dict[key].valid != 0) {
1069
+ xmlDictEntryPtr tmp;
1070
+
1071
+ for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
1072
+ tmp = tmp->next) {
1073
+ #ifdef __GNUC__
1074
+ if ((tmp->okey == skey) && (tmp->len == l)) {
1075
+ if (!memcmp(tmp->name, name, l))
1076
+ return(tmp->name);
1077
+ }
1078
+ #else
1079
+ if ((tmp->okey == skey) && (tmp->len == l) &&
1080
+ (!xmlStrncmp(tmp->name, name, l)))
1081
+ return(tmp->name);
1082
+ #endif
1083
+ nbi++;
1084
+ }
1085
+ #ifdef __GNUC__
1086
+ if ((tmp->okey == skey) && (tmp->len == l)) {
1087
+ if (!memcmp(tmp->name, name, l))
1088
+ return(tmp->name);
1089
+ }
1090
+ #else
1091
+ if ((tmp->okey == skey) && (tmp->len == l) &&
1092
+ (!xmlStrncmp(tmp->name, name, l)))
1093
+ return(tmp->name);
1094
+ #endif
1095
+ }
1096
+ }
1097
+
1098
+ /* not found */
1099
+ return(NULL);
1100
+ }
1101
+
1102
+ /**
1103
+ * xmlDictQLookup:
1104
+ * @dict: the dictionary
1105
+ * @prefix: the prefix
1106
+ * @name: the name
1107
+ *
1108
+ * Add the QName @prefix:@name to the hash @dict if not present.
1109
+ *
1110
+ * Returns the internal copy of the QName or NULL in case of internal error
1111
+ */
1112
+ const xmlChar *
1113
+ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
1114
+ unsigned long okey, key, nbi = 0;
1115
+ xmlDictEntryPtr entry;
1116
+ xmlDictEntryPtr insert;
1117
+ const xmlChar *ret;
1118
+ unsigned int len, plen, l;
1119
+
1120
+ if ((dict == NULL) || (name == NULL))
1121
+ return(NULL);
1122
+ if (prefix == NULL)
1123
+ return(xmlDictLookup(dict, name, -1));
1124
+
1125
+ l = len = strlen((const char *) name);
1126
+ plen = strlen((const char *) prefix);
1127
+ len += 1 + plen;
1128
+
1129
+ /*
1130
+ * Check for duplicate and insertion location.
1131
+ */
1132
+ okey = xmlDictComputeQKey(dict, prefix, plen, name, l);
1133
+ key = okey % dict->size;
1134
+ if (dict->dict[key].valid == 0) {
1135
+ insert = NULL;
1136
+ } else {
1137
+ for (insert = &(dict->dict[key]); insert->next != NULL;
1138
+ insert = insert->next) {
1139
+ if ((insert->okey == okey) && (insert->len == len) &&
1140
+ (xmlStrQEqual(prefix, name, insert->name)))
1141
+ return(insert->name);
1142
+ nbi++;
1143
+ }
1144
+ if ((insert->okey == okey) && (insert->len == len) &&
1145
+ (xmlStrQEqual(prefix, name, insert->name)))
1146
+ return(insert->name);
1147
+ }
1148
+
1149
+ if (dict->subdict) {
1150
+ unsigned long skey;
1151
+
1152
+ /* we cannot always reuse the same okey for the subdict */
1153
+ if (((dict->size == MIN_DICT_SIZE) &&
1154
+ (dict->subdict->size != MIN_DICT_SIZE)) ||
1155
+ ((dict->size != MIN_DICT_SIZE) &&
1156
+ (dict->subdict->size == MIN_DICT_SIZE)))
1157
+ skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l);
1158
+ else
1159
+ skey = okey;
1160
+
1161
+ key = skey % dict->subdict->size;
1162
+ if (dict->subdict->dict[key].valid != 0) {
1163
+ xmlDictEntryPtr tmp;
1164
+ for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL;
1165
+ tmp = tmp->next) {
1166
+ if ((tmp->okey == skey) && (tmp->len == len) &&
1167
+ (xmlStrQEqual(prefix, name, tmp->name)))
1168
+ return(tmp->name);
1169
+ nbi++;
1170
+ }
1171
+ if ((tmp->okey == skey) && (tmp->len == len) &&
1172
+ (xmlStrQEqual(prefix, name, tmp->name)))
1173
+ return(tmp->name);
1174
+ }
1175
+ key = okey % dict->size;
1176
+ }
1177
+
1178
+ ret = xmlDictAddQString(dict, prefix, plen, name, l);
1179
+ if (ret == NULL)
1180
+ return(NULL);
1181
+ if (insert == NULL) {
1182
+ entry = &(dict->dict[key]);
1183
+ } else {
1184
+ entry = xmlMalloc(sizeof(xmlDictEntry));
1185
+ if (entry == NULL)
1186
+ return(NULL);
1187
+ }
1188
+ entry->name = ret;
1189
+ entry->len = len;
1190
+ entry->next = NULL;
1191
+ entry->valid = 1;
1192
+ entry->okey = okey;
1193
+
1194
+ if (insert != NULL)
1195
+ insert->next = entry;
1196
+
1197
+ dict->nbElems++;
1198
+
1199
+ if ((nbi > MAX_HASH_LEN) &&
1200
+ (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN)))
1201
+ xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size);
1202
+ /* Note that entry may have been freed at this point by xmlDictGrow */
1203
+
1204
+ return(ret);
1205
+ }
1206
+
1207
+ /**
1208
+ * xmlDictOwns:
1209
+ * @dict: the dictionary
1210
+ * @str: the string
1211
+ *
1212
+ * check if a string is owned by the dictionary
1213
+ *
1214
+ * Returns 1 if true, 0 if false and -1 in case of error
1215
+ * -1 in case of error
1216
+ */
1217
+ int
1218
+ xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
1219
+ xmlDictStringsPtr pool;
1220
+
1221
+ if ((dict == NULL) || (str == NULL))
1222
+ return(-1);
1223
+ pool = dict->strings;
1224
+ while (pool != NULL) {
1225
+ if ((str >= &pool->array[0]) && (str <= pool->free))
1226
+ return(1);
1227
+ pool = pool->next;
1228
+ }
1229
+ if (dict->subdict)
1230
+ return(xmlDictOwns(dict->subdict, str));
1231
+ return(0);
1232
+ }
1233
+
1234
+ /**
1235
+ * xmlDictSize:
1236
+ * @dict: the dictionary
1237
+ *
1238
+ * Query the number of elements installed in the hash @dict.
1239
+ *
1240
+ * Returns the number of elements in the dictionary or
1241
+ * -1 in case of error
1242
+ */
1243
+ int
1244
+ xmlDictSize(xmlDictPtr dict) {
1245
+ if (dict == NULL)
1246
+ return(-1);
1247
+ if (dict->subdict)
1248
+ return(dict->nbElems + dict->subdict->nbElems);
1249
+ return(dict->nbElems);
1250
+ }
1251
+
1252
+ /**
1253
+ * xmlDictSetLimit:
1254
+ * @dict: the dictionary
1255
+ * @limit: the limit in bytes
1256
+ *
1257
+ * Set a size limit for the dictionary
1258
+ * Added in 2.9.0
1259
+ *
1260
+ * Returns the previous limit of the dictionary or 0
1261
+ */
1262
+ size_t
1263
+ xmlDictSetLimit(xmlDictPtr dict, size_t limit) {
1264
+ size_t ret;
1265
+
1266
+ if (dict == NULL)
1267
+ return(0);
1268
+ ret = dict->limit;
1269
+ dict->limit = limit;
1270
+ return(ret);
1271
+ }
1272
+
1273
+ /**
1274
+ * xmlDictGetUsage:
1275
+ * @dict: the dictionary
1276
+ *
1277
+ * Get how much memory is used by a dictionary for strings
1278
+ * Added in 2.9.0
1279
+ *
1280
+ * Returns the amount of strings allocated
1281
+ */
1282
+ size_t
1283
+ xmlDictGetUsage(xmlDictPtr dict) {
1284
+ xmlDictStringsPtr pool;
1285
+ size_t limit = 0;
1286
+
1287
+ if (dict == NULL)
1288
+ return(0);
1289
+ pool = dict->strings;
1290
+ while (pool != NULL) {
1291
+ limit += pool->size;
1292
+ pool = pool->next;
1293
+ }
1294
+ return(limit);
1295
+ }
1296
+
1297
+ #define bottom_dict
1298
+ #include "elfgcchack.h"