Index: third_party/libxml/src/dict.c |
diff --git a/third_party/libxml/src/dict.c b/third_party/libxml/src/dict.c |
index 3eff2315e94112089cf487707a02f409740031fe..5f71d55d736f7d752c71ae720e5d3d6e487b493b 100644 |
--- a/third_party/libxml/src/dict.c |
+++ b/third_party/libxml/src/dict.c |
@@ -2,7 +2,7 @@ |
* dict.c: dictionary of reusable strings, just used to avoid allocation |
* and freeing operations. |
* |
- * Copyright (C) 2003 Daniel Veillard. |
+ * Copyright (C) 2003-2012 Daniel Veillard. |
* |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
@@ -19,6 +19,29 @@ |
#define IN_LIBXML |
#include "libxml.h" |
+#include <limits.h> |
+#ifdef HAVE_STDLIB_H |
+#include <stdlib.h> |
+#endif |
+#ifdef HAVE_TIME_H |
+#include <time.h> |
+#endif |
+ |
+/* |
+ * Following http://www.ocert.org/advisories/ocert-2011-003.html |
+ * it seems that having hash randomization might be a good idea |
+ * when using XML with untrusted data |
+ * Note1: that it works correctly only if compiled with WITH_BIG_KEY |
+ * which is the default. |
+ * Note2: the fast function used for a small dict won't protect very |
+ * well but since the attack is based on growing a very big hash |
+ * list we will use the BigKey algo as soon as the hash size grows |
+ * over MIN_DICT_SIZE so this actually works |
+ */ |
+#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME) |
+#define DICT_RANDOMIZATION |
+#endif |
+ |
#include <string.h> |
#ifdef HAVE_STDINT_H |
#include <stdint.h> |
@@ -44,23 +67,23 @@ typedef unsigned __int32 uint32_t; |
#define WITH_BIG_KEY |
#ifdef WITH_BIG_KEY |
-#define xmlDictComputeKey(dict, name, len) \ |
- (((dict)->size == MIN_DICT_SIZE) ? \ |
- xmlDictComputeFastKey(name, len) : \ |
- xmlDictComputeBigKey(name, len)) |
- |
-#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
- (((prefix) == NULL) ? \ |
- (xmlDictComputeKey(dict, name, len)) : \ |
- (((dict)->size == MIN_DICT_SIZE) ? \ |
- xmlDictComputeFastQKey(prefix, plen, name, len) : \ |
- xmlDictComputeBigQKey(prefix, plen, name, len))) |
+#define xmlDictComputeKey(dict, name, len) \ |
+ (((dict)->size == MIN_DICT_SIZE) ? \ |
+ xmlDictComputeFastKey(name, len, (dict)->seed) : \ |
+ xmlDictComputeBigKey(name, len, (dict)->seed)) |
+ |
+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
+ (((prefix) == NULL) ? \ |
+ (xmlDictComputeKey(dict, name, len)) : \ |
+ (((dict)->size == MIN_DICT_SIZE) ? \ |
+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \ |
+ xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed))) |
#else /* !WITH_BIG_KEY */ |
-#define xmlDictComputeKey(dict, name, len) \ |
- xmlDictComputeFastKey(name, len) |
-#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
- xmlDictComputeFastQKey(prefix, plen, name, len) |
+#define xmlDictComputeKey(dict, name, len) \ |
+ xmlDictComputeFastKey(name, len, (dict)->seed) |
+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
+ xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) |
#endif /* WITH_BIG_KEY */ |
/* |
@@ -71,7 +94,7 @@ typedef xmlDictEntry *xmlDictEntryPtr; |
struct _xmlDictEntry { |
struct _xmlDictEntry *next; |
const xmlChar *name; |
- int len; |
+ unsigned int len; |
int valid; |
unsigned long okey; |
}; |
@@ -82,8 +105,8 @@ struct _xmlDictStrings { |
xmlDictStringsPtr next; |
xmlChar *free; |
xmlChar *end; |
- int size; |
- int nbStrings; |
+ size_t size; |
+ size_t nbStrings; |
xmlChar array[1]; |
}; |
/* |
@@ -93,11 +116,15 @@ struct _xmlDict { |
int ref_counter; |
struct _xmlDictEntry *dict; |
- int size; |
- int nbElems; |
+ size_t size; |
+ unsigned int nbElems; |
xmlDictStringsPtr strings; |
struct _xmlDict *subdict; |
+ /* used for randomization */ |
+ int seed; |
+ /* used to impose a limit on size */ |
+ size_t limit; |
}; |
/* |
@@ -111,28 +138,84 @@ static xmlRMutexPtr xmlDictMutex = NULL; |
*/ |
static int xmlDictInitialized = 0; |
+#ifdef DICT_RANDOMIZATION |
+#ifdef HAVE_RAND_R |
+/* |
+ * Internal data for random function, protected by xmlDictMutex |
+ */ |
+static unsigned int rand_seed = 0; |
+#endif |
+#endif |
+ |
/** |
* xmlInitializeDict: |
* |
* Do the dictionary mutex initialization. |
+ * this function is deprecated |
+ * |
+ * Returns 0 if initialization was already done, and 1 if that |
+ * call led to the initialization |
+ */ |
+int xmlInitializeDict(void) { |
+ return(0); |
+} |
+ |
+/** |
+ * __xmlInitializeDict: |
+ * |
+ * This function is not public |
+ * Do the dictionary mutex initialization. |
* this function is not thread safe, initialization should |
- * preferably be done once at startup |
+ * normally be done once at setup when called from xmlOnceInit() |
+ * we may also land in this code if thread support is not compiled in |
+ * |
+ * Returns 0 if initialization was already done, and 1 if that |
+ * call led to the initialization |
*/ |
-static int xmlInitializeDict(void) { |
+int __xmlInitializeDict(void) { |
if (xmlDictInitialized) |
return(1); |
if ((xmlDictMutex = xmlNewRMutex()) == NULL) |
return(0); |
+ xmlRMutexLock(xmlDictMutex); |
+#ifdef DICT_RANDOMIZATION |
+#ifdef HAVE_RAND_R |
+ rand_seed = time(NULL); |
+ rand_r(& rand_seed); |
+#else |
+ srand(time(NULL)); |
+#endif |
+#endif |
xmlDictInitialized = 1; |
+ xmlRMutexUnlock(xmlDictMutex); |
return(1); |
} |
+#ifdef DICT_RANDOMIZATION |
+int __xmlRandom(void) { |
+ int ret; |
+ |
+ if (xmlDictInitialized == 0) |
+ __xmlInitializeDict(); |
+ |
+ xmlRMutexLock(xmlDictMutex); |
+#ifdef HAVE_RAND_R |
+ ret = rand_r(& rand_seed); |
+#else |
+ ret = rand(); |
+#endif |
+ xmlRMutexUnlock(xmlDictMutex); |
+ return(ret); |
+} |
+#endif |
+ |
/** |
* xmlDictCleanup: |
* |
- * Free the dictionary mutex. |
+ * Free the dictionary mutex. Do not call unless sure the library |
+ * is not in use anymore ! |
*/ |
void |
xmlDictCleanup(void) { |
@@ -148,17 +231,18 @@ xmlDictCleanup(void) { |
* xmlDictAddString: |
* @dict: the dictionnary |
* @name: the name of the userdata |
- * @len: the length of the name, if -1 it is recomputed |
+ * @len: the length of the name |
* |
* Add the string to the array[s] |
* |
* Returns the pointer of the local string, or NULL in case of error. |
*/ |
static const xmlChar * |
-xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { |
+xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) { |
xmlDictStringsPtr pool; |
const xmlChar *ret; |
- int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
+ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
+ size_t limit = 0; |
#ifdef DICT_DEBUG_PATTERNS |
fprintf(stderr, "-"); |
@@ -168,15 +252,20 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { |
if (pool->end - pool->free > namelen) |
goto found_pool; |
if (pool->size > size) size = pool->size; |
+ limit += pool->size; |
pool = pool->next; |
} |
/* |
* Not found, need to allocate |
*/ |
if (pool == NULL) { |
+ if ((dict->limit > 0) && (limit > dict->limit)) { |
+ return(NULL); |
+ } |
+ |
if (size == 0) size = 1000; |
else size *= 4; /* exponential growth */ |
- if (size < 4 * namelen) |
+ if (size < 4 * namelen) |
size = 4 * namelen; /* just in case ! */ |
pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); |
if (pool == NULL) |
@@ -206,19 +295,20 @@ found_pool: |
* @prefix: the prefix of the userdata |
* @plen: the prefix length |
* @name: the name of the userdata |
- * @len: the length of the name, if -1 it is recomputed |
+ * @len: the length of the name |
* |
* Add the QName to the array[s] |
* |
* Returns the pointer of the local string, or NULL in case of error. |
*/ |
static const xmlChar * |
-xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen, |
- const xmlChar *name, int namelen) |
+xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen, |
+ const xmlChar *name, unsigned int namelen) |
{ |
xmlDictStringsPtr pool; |
const xmlChar *ret; |
- int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
+ size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
+ size_t limit = 0; |
if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); |
@@ -230,12 +320,17 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen, |
if (pool->end - pool->free > namelen + plen + 1) |
goto found_pool; |
if (pool->size > size) size = pool->size; |
+ limit += pool->size; |
pool = pool->next; |
} |
/* |
* Not found, need to allocate |
*/ |
if (pool == NULL) { |
+ if ((dict->limit > 0) && (limit > dict->limit)) { |
+ return(NULL); |
+ } |
+ |
if (size == 0) size = 1000; |
else size *= 4; /* exponential growth */ |
if (size < 4 * (namelen + plen + 1)) |
@@ -277,13 +372,13 @@ found_pool: |
*/ |
static uint32_t |
-xmlDictComputeBigKey(const xmlChar* data, int namelen) { |
+xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) { |
uint32_t hash; |
int i; |
if (namelen <= 0 || data == NULL) return(0); |
- hash = 0; |
+ hash = seed; |
for (i = 0;i < namelen; i++) { |
hash += data[i]; |
@@ -310,12 +405,12 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen) { |
*/ |
static unsigned long |
xmlDictComputeBigQKey(const xmlChar *prefix, int plen, |
- const xmlChar *name, int len) |
+ const xmlChar *name, int len, int seed) |
{ |
uint32_t hash; |
int i; |
- hash = 0; |
+ hash = seed; |
for (i = 0;i < plen; i++) { |
hash += prefix[i]; |
@@ -346,8 +441,8 @@ xmlDictComputeBigQKey(const xmlChar *prefix, int plen, |
* for low hash table fill. |
*/ |
static unsigned long |
-xmlDictComputeFastKey(const xmlChar *name, int namelen) { |
- unsigned long value = 0L; |
+xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { |
+ unsigned long value = seed; |
if (name == NULL) return(0); |
value = *name; |
@@ -381,9 +476,9 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen) { |
*/ |
static unsigned long |
xmlDictComputeFastQKey(const xmlChar *prefix, int plen, |
- const xmlChar *name, int len) |
+ const xmlChar *name, int len, int seed) |
{ |
- unsigned long value = 0L; |
+ unsigned long value = (unsigned long) seed; |
if (plen == 0) |
value += 30 * (unsigned long) ':'; |
@@ -442,7 +537,7 @@ xmlDictCreate(void) { |
xmlDictPtr dict; |
if (!xmlDictInitialized) |
- if (!xmlInitializeDict()) |
+ if (!__xmlInitializeDict()) |
return(NULL); |
#ifdef DICT_DEBUG_PATTERNS |
@@ -452,6 +547,7 @@ xmlDictCreate(void) { |
dict = xmlMalloc(sizeof(xmlDict)); |
if (dict) { |
dict->ref_counter = 1; |
+ dict->limit = 0; |
dict->size = MIN_DICT_SIZE; |
dict->nbElems = 0; |
@@ -460,6 +556,11 @@ xmlDictCreate(void) { |
dict->subdict = NULL; |
if (dict->dict) { |
memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); |
+#ifdef DICT_RANDOMIZATION |
+ dict->seed = __xmlRandom(); |
+#else |
+ dict->seed = 0; |
+#endif |
return(dict); |
} |
xmlFree(dict); |
@@ -486,6 +587,7 @@ xmlDictCreateSub(xmlDictPtr sub) { |
#ifdef DICT_DEBUG_PATTERNS |
fprintf(stderr, "R"); |
#endif |
+ dict->seed = sub->seed; |
dict->subdict = sub; |
xmlDictReference(dict->subdict); |
} |
@@ -503,7 +605,7 @@ xmlDictCreateSub(xmlDictPtr sub) { |
int |
xmlDictReference(xmlDictPtr dict) { |
if (!xmlDictInitialized) |
- if (!xmlInitializeDict()) |
+ if (!__xmlInitializeDict()) |
return(-1); |
if (dict == NULL) return -1; |
@@ -523,9 +625,9 @@ xmlDictReference(xmlDictPtr dict) { |
* Returns 0 in case of success, -1 in case of failure |
*/ |
static int |
-xmlDictGrow(xmlDictPtr dict, int size) { |
+xmlDictGrow(xmlDictPtr dict, size_t size) { |
unsigned long key, okey; |
- int oldsize, i; |
+ size_t oldsize, i; |
xmlDictEntryPtr iter, next; |
struct _xmlDictEntry *olddict; |
#ifdef DEBUG_GROW |
@@ -642,7 +744,7 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
#ifdef DEBUG_GROW |
xmlGenericError(xmlGenericErrorContext, |
- "xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); |
+ "xmlDictGrow : from %lu to %lu, %u elems\n", oldsize, size, nbElem); |
#endif |
return(ret); |
@@ -657,7 +759,7 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
*/ |
void |
xmlDictFree(xmlDictPtr dict) { |
- int i; |
+ size_t i; |
xmlDictEntryPtr iter; |
xmlDictEntryPtr next; |
int inside_dict = 0; |
@@ -667,7 +769,7 @@ xmlDictFree(xmlDictPtr dict) { |
return; |
if (!xmlDictInitialized) |
- if (!xmlInitializeDict()) |
+ if (!__xmlInitializeDict()) |
return; |
/* decrement the counter, it may be shared by a parser and docs */ |
@@ -726,17 +828,24 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
xmlDictEntryPtr entry; |
xmlDictEntryPtr insert; |
const xmlChar *ret; |
+ unsigned int l; |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
if (len < 0) |
- len = strlen((const char *) name); |
+ l = strlen((const char *) name); |
+ else |
+ l = len; |
+ |
+ if (((dict->limit > 0) && (l >= dict->limit)) || |
+ (l > INT_MAX / 2)) |
+ return(NULL); |
/* |
* Check for duplicate and insertion location. |
*/ |
- okey = xmlDictComputeKey(dict, name, len); |
+ okey = xmlDictComputeKey(dict, name, l); |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
@@ -744,25 +853,25 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
#ifdef __GNUC__ |
- if ((insert->okey == okey) && (insert->len == len)) { |
- if (!memcmp(insert->name, name, len)) |
+ if ((insert->okey == okey) && (insert->len == l)) { |
+ if (!memcmp(insert->name, name, l)) |
return(insert->name); |
} |
#else |
- if ((insert->okey == okey) && (insert->len == len) && |
- (!xmlStrncmp(insert->name, name, len))) |
+ if ((insert->okey == okey) && (insert->len == l) && |
+ (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if ((insert->okey == okey) && (insert->len == len)) { |
- if (!memcmp(insert->name, name, len)) |
+ if ((insert->okey == okey) && (insert->len == l)) { |
+ if (!memcmp(insert->name, name, l)) |
return(insert->name); |
} |
#else |
- if ((insert->okey == okey) && (insert->len == len) && |
- (!xmlStrncmp(insert->name, name, len))) |
+ if ((insert->okey == okey) && (insert->len == l) && |
+ (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
#endif |
} |
@@ -775,7 +884,7 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
(dict->subdict->size != MIN_DICT_SIZE)) || |
((dict->size != MIN_DICT_SIZE) && |
(dict->subdict->size == MIN_DICT_SIZE))) |
- skey = xmlDictComputeKey(dict->subdict, name, len); |
+ skey = xmlDictComputeKey(dict->subdict, name, l); |
else |
skey = okey; |
@@ -786,32 +895,32 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
#ifdef __GNUC__ |
- if ((tmp->okey == skey) && (tmp->len == len)) { |
- if (!memcmp(tmp->name, name, len)) |
+ if ((tmp->okey == skey) && (tmp->len == l)) { |
+ if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
} |
#else |
- if ((tmp->okey == skey) && (tmp->len == len) && |
- (!xmlStrncmp(tmp->name, name, len))) |
+ if ((tmp->okey == skey) && (tmp->len == l) && |
+ (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if ((tmp->okey == skey) && (tmp->len == len)) { |
- if (!memcmp(tmp->name, name, len)) |
+ if ((tmp->okey == skey) && (tmp->len == l)) { |
+ if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
} |
#else |
- if ((tmp->okey == skey) && (tmp->len == len) && |
- (!xmlStrncmp(tmp->name, name, len))) |
+ if ((tmp->okey == skey) && (tmp->len == l) && |
+ (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
#endif |
} |
key = okey % dict->size; |
} |
- ret = xmlDictAddString(dict, name, len); |
+ ret = xmlDictAddString(dict, name, l); |
if (ret == NULL) |
return(NULL); |
if (insert == NULL) { |
@@ -822,13 +931,13 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
return(NULL); |
} |
entry->name = ret; |
- entry->len = len; |
+ entry->len = l; |
entry->next = NULL; |
entry->valid = 1; |
entry->okey = okey; |
- if (insert != NULL) |
+ if (insert != NULL) |
insert->next = entry; |
dict->nbElems++; |
@@ -857,17 +966,23 @@ const xmlChar * |
xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
unsigned long key, okey, nbi = 0; |
xmlDictEntryPtr insert; |
+ unsigned int l; |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
if (len < 0) |
- len = strlen((const char *) name); |
+ l = strlen((const char *) name); |
+ else |
+ l = len; |
+ if (((dict->limit > 0) && (l >= dict->limit)) || |
+ (l > INT_MAX / 2)) |
+ return(NULL); |
/* |
* Check for duplicate and insertion location. |
*/ |
- okey = xmlDictComputeKey(dict, name, len); |
+ okey = xmlDictComputeKey(dict, name, l); |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
@@ -875,25 +990,25 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
#ifdef __GNUC__ |
- if ((insert->okey == okey) && (insert->len == len)) { |
- if (!memcmp(insert->name, name, len)) |
+ if ((insert->okey == okey) && (insert->len == l)) { |
+ if (!memcmp(insert->name, name, l)) |
return(insert->name); |
} |
#else |
- if ((insert->okey == okey) && (insert->len == len) && |
- (!xmlStrncmp(insert->name, name, len))) |
+ if ((insert->okey == okey) && (insert->len == l) && |
+ (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if ((insert->okey == okey) && (insert->len == len)) { |
- if (!memcmp(insert->name, name, len)) |
+ if ((insert->okey == okey) && (insert->len == l)) { |
+ if (!memcmp(insert->name, name, l)) |
return(insert->name); |
} |
#else |
- if ((insert->okey == okey) && (insert->len == len) && |
- (!xmlStrncmp(insert->name, name, len))) |
+ if ((insert->okey == okey) && (insert->len == l) && |
+ (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
#endif |
} |
@@ -906,7 +1021,7 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
(dict->subdict->size != MIN_DICT_SIZE)) || |
((dict->size != MIN_DICT_SIZE) && |
(dict->subdict->size == MIN_DICT_SIZE))) |
- skey = xmlDictComputeKey(dict->subdict, name, len); |
+ skey = xmlDictComputeKey(dict->subdict, name, l); |
else |
skey = okey; |
@@ -917,25 +1032,25 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
#ifdef __GNUC__ |
- if ((tmp->okey == skey) && (tmp->len == len)) { |
- if (!memcmp(tmp->name, name, len)) |
+ if ((tmp->okey == skey) && (tmp->len == l)) { |
+ if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
} |
#else |
- if ((tmp->okey == skey) && (tmp->len == len) && |
- (!xmlStrncmp(tmp->name, name, len))) |
+ if ((tmp->okey == skey) && (tmp->len == l) && |
+ (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if ((tmp->okey == skey) && (tmp->len == len)) { |
- if (!memcmp(tmp->name, name, len)) |
+ if ((tmp->okey == skey) && (tmp->len == l)) { |
+ if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
} |
#else |
- if ((tmp->okey == skey) && (tmp->len == len) && |
- (!xmlStrncmp(tmp->name, name, len))) |
+ if ((tmp->okey == skey) && (tmp->len == l) && |
+ (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
#endif |
} |
@@ -961,7 +1076,7 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { |
xmlDictEntryPtr entry; |
xmlDictEntryPtr insert; |
const xmlChar *ret; |
- int len, plen, l; |
+ unsigned int len, plen, l; |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
@@ -1037,7 +1152,7 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { |
entry->valid = 1; |
entry->okey = okey; |
- if (insert != NULL) |
+ if (insert != NULL) |
insert->next = entry; |
dict->nbElems++; |
@@ -1095,6 +1210,50 @@ xmlDictSize(xmlDictPtr dict) { |
return(dict->nbElems); |
} |
+/** |
+ * xmlDictSetLimit: |
+ * @dict: the dictionnary |
+ * @limit: the limit in bytes |
+ * |
+ * Set a size limit for the dictionary |
+ * Added in 2.9.0 |
+ * |
+ * Returns the previous limit of the dictionary or 0 |
+ */ |
+size_t |
+xmlDictSetLimit(xmlDictPtr dict, size_t limit) { |
+ size_t ret; |
+ |
+ if (dict == NULL) |
+ return(0); |
+ ret = dict->limit; |
+ dict->limit = limit; |
+ return(ret); |
+} |
+ |
+/** |
+ * xmlDictGetUsage: |
+ * @dict: the dictionnary |
+ * |
+ * Get how much memory is used by a dictionary for strings |
+ * Added in 2.9.0 |
+ * |
+ * Returns the amount of strings allocated |
+ */ |
+size_t |
+xmlDictGetUsage(xmlDictPtr dict) { |
+ xmlDictStringsPtr pool; |
+ size_t limit = 0; |
+ |
+ if (dict == NULL) |
+ return(0); |
+ pool = dict->strings; |
+ while (pool != NULL) { |
+ limit += pool->size; |
+ pool = pool->next; |
+ } |
+ return(limit); |
+} |
#define bottom_dict |
#include "elfgcchack.h" |