version 1.1, 2012/02/21 23:37:58
|
version 1.1.1.3, 2014/06/15 19:53:29
|
Line 2
|
Line 2
|
* dict.c: dictionary of reusable strings, just used to avoid allocation |
* dict.c: dictionary of reusable strings, just used to avoid allocation |
* and freeing operations. |
* 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 |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 19
|
Line 19
|
#define IN_LIBXML |
#define IN_LIBXML |
#include "libxml.h" |
#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> |
#include <string.h> |
#ifdef HAVE_STDINT_H |
#ifdef HAVE_STDINT_H |
#include <stdint.h> |
#include <stdint.h> |
Line 44 typedef unsigned __int32 uint32_t;
|
Line 67 typedef unsigned __int32 uint32_t;
|
#define WITH_BIG_KEY |
#define WITH_BIG_KEY |
|
|
#ifdef WITH_BIG_KEY |
#ifdef WITH_BIG_KEY |
#define xmlDictComputeKey(dict, name, len) \ | #define xmlDictComputeKey(dict, name, len) \ |
(((dict)->size == MIN_DICT_SIZE) ? \ | (((dict)->size == MIN_DICT_SIZE) ? \ |
xmlDictComputeFastKey(name, len) : \ | xmlDictComputeFastKey(name, len, (dict)->seed) : \ |
xmlDictComputeBigKey(name, len)) | xmlDictComputeBigKey(name, len, (dict)->seed)) |
|
|
#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ | #define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
(((prefix) == NULL) ? \ | (((prefix) == NULL) ? \ |
(xmlDictComputeKey(dict, name, len)) : \ | (xmlDictComputeKey(dict, name, len)) : \ |
(((dict)->size == MIN_DICT_SIZE) ? \ | (((dict)->size == MIN_DICT_SIZE) ? \ |
xmlDictComputeFastQKey(prefix, plen, name, len) : \ | xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) : \ |
xmlDictComputeBigQKey(prefix, plen, name, len))) | xmlDictComputeBigQKey(prefix, plen, name, len, (dict)->seed))) |
|
|
#else /* !WITH_BIG_KEY */ |
#else /* !WITH_BIG_KEY */ |
#define xmlDictComputeKey(dict, name, len) \ | #define xmlDictComputeKey(dict, name, len) \ |
xmlDictComputeFastKey(name, len) | xmlDictComputeFastKey(name, len, (dict)->seed) |
#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ | #define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
xmlDictComputeFastQKey(prefix, plen, name, len) | xmlDictComputeFastQKey(prefix, plen, name, len, (dict)->seed) |
#endif /* WITH_BIG_KEY */ |
#endif /* WITH_BIG_KEY */ |
|
|
/* |
/* |
Line 71 typedef xmlDictEntry *xmlDictEntryPtr;
|
Line 94 typedef xmlDictEntry *xmlDictEntryPtr;
|
struct _xmlDictEntry { |
struct _xmlDictEntry { |
struct _xmlDictEntry *next; |
struct _xmlDictEntry *next; |
const xmlChar *name; |
const xmlChar *name; |
int len; | unsigned int len; |
int valid; |
int valid; |
unsigned long okey; |
unsigned long okey; |
}; |
}; |
Line 82 struct _xmlDictStrings {
|
Line 105 struct _xmlDictStrings {
|
xmlDictStringsPtr next; |
xmlDictStringsPtr next; |
xmlChar *free; |
xmlChar *free; |
xmlChar *end; |
xmlChar *end; |
int size; | size_t size; |
int nbStrings; | size_t nbStrings; |
xmlChar array[1]; |
xmlChar array[1]; |
}; |
}; |
/* |
/* |
Line 93 struct _xmlDict {
|
Line 116 struct _xmlDict {
|
int ref_counter; |
int ref_counter; |
|
|
struct _xmlDictEntry *dict; |
struct _xmlDictEntry *dict; |
int size; | size_t size; |
int nbElems; | unsigned int nbElems; |
xmlDictStringsPtr strings; |
xmlDictStringsPtr strings; |
|
|
struct _xmlDict *subdict; |
struct _xmlDict *subdict; |
|
/* used for randomization */ |
|
int seed; |
|
/* used to impose a limit on size */ |
|
size_t limit; |
}; |
}; |
|
|
/* |
/* |
Line 111 static xmlRMutexPtr xmlDictMutex = NULL;
|
Line 138 static xmlRMutexPtr xmlDictMutex = NULL;
|
*/ |
*/ |
static int xmlDictInitialized = 0; |
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: |
* xmlInitializeDict: |
* |
* |
* Do the dictionary mutex initialization. |
* 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 |
* 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) |
if (xmlDictInitialized) |
return(1); |
return(1); |
|
|
if ((xmlDictMutex = xmlNewRMutex()) == NULL) |
if ((xmlDictMutex = xmlNewRMutex()) == NULL) |
return(0); |
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; |
xmlDictInitialized = 1; |
|
xmlRMutexUnlock(xmlDictMutex); |
return(1); |
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: |
* xmlDictCleanup: |
* |
* |
* Free the dictionary mutex. | * Free the dictionary mutex. Do not call unless sure the library |
| * is not in use anymore ! |
*/ |
*/ |
void |
void |
xmlDictCleanup(void) { |
xmlDictCleanup(void) { |
Line 148 xmlDictCleanup(void) {
|
Line 231 xmlDictCleanup(void) {
|
* xmlDictAddString: |
* xmlDictAddString: |
* @dict: the dictionnary |
* @dict: the dictionnary |
* @name: the name of the userdata |
* @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] |
* Add the string to the array[s] |
* |
* |
* Returns the pointer of the local string, or NULL in case of error. |
* Returns the pointer of the local string, or NULL in case of error. |
*/ |
*/ |
static const xmlChar * |
static const xmlChar * |
xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { | xmlDictAddString(xmlDictPtr dict, const xmlChar *name, unsigned int namelen) { |
xmlDictStringsPtr pool; |
xmlDictStringsPtr pool; |
const xmlChar *ret; |
const xmlChar *ret; |
int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ | size_t size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
| size_t limit = 0; |
|
|
#ifdef DICT_DEBUG_PATTERNS |
#ifdef DICT_DEBUG_PATTERNS |
fprintf(stderr, "-"); |
fprintf(stderr, "-"); |
Line 168 xmlDictAddString(xmlDictPtr dict, const xmlChar *name,
|
Line 252 xmlDictAddString(xmlDictPtr dict, const xmlChar *name,
|
if (pool->end - pool->free > namelen) |
if (pool->end - pool->free > namelen) |
goto found_pool; |
goto found_pool; |
if (pool->size > size) size = pool->size; |
if (pool->size > size) size = pool->size; |
|
limit += pool->size; |
pool = pool->next; |
pool = pool->next; |
} |
} |
/* |
/* |
* Not found, need to allocate |
* Not found, need to allocate |
*/ |
*/ |
if (pool == NULL) { |
if (pool == NULL) { |
|
if ((dict->limit > 0) && (limit > dict->limit)) { |
|
return(NULL); |
|
} |
|
|
if (size == 0) size = 1000; |
if (size == 0) size = 1000; |
else size *= 4; /* exponential growth */ |
else size *= 4; /* exponential growth */ |
if (size < 4 * namelen) | if (size < 4 * namelen) |
size = 4 * namelen; /* just in case ! */ |
size = 4 * namelen; /* just in case ! */ |
pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); |
pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); |
if (pool == NULL) |
if (pool == NULL) |
Line 206 found_pool:
|
Line 295 found_pool:
|
* @prefix: the prefix of the userdata |
* @prefix: the prefix of the userdata |
* @plen: the prefix length |
* @plen: the prefix length |
* @name: the name of the userdata |
* @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] |
* Add the QName to the array[s] |
* |
* |
* Returns the pointer of the local string, or NULL in case of error. |
* Returns the pointer of the local string, or NULL in case of error. |
*/ |
*/ |
static const xmlChar * |
static const xmlChar * |
xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen, | xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, unsigned int plen, |
const xmlChar *name, int namelen) | const xmlChar *name, unsigned int namelen) |
{ |
{ |
xmlDictStringsPtr pool; |
xmlDictStringsPtr pool; |
const xmlChar *ret; |
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)); |
if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); |
|
|
Line 230 xmlDictAddQString(xmlDictPtr dict, const xmlChar *pref
|
Line 320 xmlDictAddQString(xmlDictPtr dict, const xmlChar *pref
|
if (pool->end - pool->free > namelen + plen + 1) |
if (pool->end - pool->free > namelen + plen + 1) |
goto found_pool; |
goto found_pool; |
if (pool->size > size) size = pool->size; |
if (pool->size > size) size = pool->size; |
|
limit += pool->size; |
pool = pool->next; |
pool = pool->next; |
} |
} |
/* |
/* |
* Not found, need to allocate |
* Not found, need to allocate |
*/ |
*/ |
if (pool == NULL) { |
if (pool == NULL) { |
|
if ((dict->limit > 0) && (limit > dict->limit)) { |
|
return(NULL); |
|
} |
|
|
if (size == 0) size = 1000; |
if (size == 0) size = 1000; |
else size *= 4; /* exponential growth */ |
else size *= 4; /* exponential growth */ |
if (size < 4 * (namelen + plen + 1)) |
if (size < 4 * (namelen + plen + 1)) |
Line 277 found_pool:
|
Line 372 found_pool:
|
*/ |
*/ |
|
|
static uint32_t |
static uint32_t |
xmlDictComputeBigKey(const xmlChar* data, int namelen) { | xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) { |
uint32_t hash; |
uint32_t hash; |
int i; |
int i; |
|
|
if (namelen <= 0 || data == NULL) return(0); |
if (namelen <= 0 || data == NULL) return(0); |
|
|
hash = 0; | hash = seed; |
|
|
for (i = 0;i < namelen; i++) { |
for (i = 0;i < namelen; i++) { |
hash += data[i]; |
hash += data[i]; |
Line 310 xmlDictComputeBigKey(const xmlChar* data, int namelen)
|
Line 405 xmlDictComputeBigKey(const xmlChar* data, int namelen)
|
*/ |
*/ |
static unsigned long |
static unsigned long |
xmlDictComputeBigQKey(const xmlChar *prefix, int plen, |
xmlDictComputeBigQKey(const xmlChar *prefix, int plen, |
const xmlChar *name, int len) | const xmlChar *name, int len, int seed) |
{ |
{ |
uint32_t hash; |
uint32_t hash; |
int i; |
int i; |
|
|
hash = 0; | hash = seed; |
|
|
for (i = 0;i < plen; i++) { |
for (i = 0;i < plen; i++) { |
hash += prefix[i]; |
hash += prefix[i]; |
Line 346 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
|
Line 441 xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
|
* for low hash table fill. |
* for low hash table fill. |
*/ |
*/ |
static unsigned long |
static unsigned long |
xmlDictComputeFastKey(const xmlChar *name, int namelen) { | xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { |
unsigned long value = 0L; | unsigned long value = seed; |
|
|
if (name == NULL) return(0); |
if (name == NULL) return(0); |
value = *name; |
value = *name; |
Line 381 xmlDictComputeFastKey(const xmlChar *name, int namelen
|
Line 476 xmlDictComputeFastKey(const xmlChar *name, int namelen
|
*/ |
*/ |
static unsigned long |
static unsigned long |
xmlDictComputeFastQKey(const xmlChar *prefix, int plen, |
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) |
if (plen == 0) |
value += 30 * (unsigned long) ':'; |
value += 30 * (unsigned long) ':'; |
Line 442 xmlDictCreate(void) {
|
Line 537 xmlDictCreate(void) {
|
xmlDictPtr dict; |
xmlDictPtr dict; |
|
|
if (!xmlDictInitialized) |
if (!xmlDictInitialized) |
if (!xmlInitializeDict()) | if (!__xmlInitializeDict()) |
return(NULL); |
return(NULL); |
|
|
#ifdef DICT_DEBUG_PATTERNS |
#ifdef DICT_DEBUG_PATTERNS |
Line 452 xmlDictCreate(void) {
|
Line 547 xmlDictCreate(void) {
|
dict = xmlMalloc(sizeof(xmlDict)); |
dict = xmlMalloc(sizeof(xmlDict)); |
if (dict) { |
if (dict) { |
dict->ref_counter = 1; |
dict->ref_counter = 1; |
|
dict->limit = 0; |
|
|
dict->size = MIN_DICT_SIZE; |
dict->size = MIN_DICT_SIZE; |
dict->nbElems = 0; |
dict->nbElems = 0; |
Line 460 xmlDictCreate(void) {
|
Line 556 xmlDictCreate(void) {
|
dict->subdict = NULL; |
dict->subdict = NULL; |
if (dict->dict) { |
if (dict->dict) { |
memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); |
memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry)); |
|
#ifdef DICT_RANDOMIZATION |
|
dict->seed = __xmlRandom(); |
|
#else |
|
dict->seed = 0; |
|
#endif |
return(dict); |
return(dict); |
} |
} |
xmlFree(dict); |
xmlFree(dict); |
Line 486 xmlDictCreateSub(xmlDictPtr sub) {
|
Line 587 xmlDictCreateSub(xmlDictPtr sub) {
|
#ifdef DICT_DEBUG_PATTERNS |
#ifdef DICT_DEBUG_PATTERNS |
fprintf(stderr, "R"); |
fprintf(stderr, "R"); |
#endif |
#endif |
|
dict->seed = sub->seed; |
dict->subdict = sub; |
dict->subdict = sub; |
xmlDictReference(dict->subdict); |
xmlDictReference(dict->subdict); |
} |
} |
Line 503 xmlDictCreateSub(xmlDictPtr sub) {
|
Line 605 xmlDictCreateSub(xmlDictPtr sub) {
|
int |
int |
xmlDictReference(xmlDictPtr dict) { |
xmlDictReference(xmlDictPtr dict) { |
if (!xmlDictInitialized) |
if (!xmlDictInitialized) |
if (!xmlInitializeDict()) | if (!__xmlInitializeDict()) |
return(-1); |
return(-1); |
|
|
if (dict == NULL) return -1; |
if (dict == NULL) return -1; |
Line 523 xmlDictReference(xmlDictPtr dict) {
|
Line 625 xmlDictReference(xmlDictPtr dict) {
|
* Returns 0 in case of success, -1 in case of failure |
* Returns 0 in case of success, -1 in case of failure |
*/ |
*/ |
static int |
static int |
xmlDictGrow(xmlDictPtr dict, int size) { | xmlDictGrow(xmlDictPtr dict, size_t size) { |
unsigned long key, okey; |
unsigned long key, okey; |
int oldsize, i; | size_t oldsize, i; |
xmlDictEntryPtr iter, next; |
xmlDictEntryPtr iter, next; |
struct _xmlDictEntry *olddict; |
struct _xmlDictEntry *olddict; |
#ifdef DEBUG_GROW |
#ifdef DEBUG_GROW |
Line 642 xmlDictGrow(xmlDictPtr dict, int size) {
|
Line 744 xmlDictGrow(xmlDictPtr dict, int size) {
|
|
|
#ifdef DEBUG_GROW |
#ifdef DEBUG_GROW |
xmlGenericError(xmlGenericErrorContext, |
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 |
#endif |
|
|
return(ret); |
return(ret); |
Line 657 xmlDictGrow(xmlDictPtr dict, int size) {
|
Line 759 xmlDictGrow(xmlDictPtr dict, int size) {
|
*/ |
*/ |
void |
void |
xmlDictFree(xmlDictPtr dict) { |
xmlDictFree(xmlDictPtr dict) { |
int i; | size_t i; |
xmlDictEntryPtr iter; |
xmlDictEntryPtr iter; |
xmlDictEntryPtr next; |
xmlDictEntryPtr next; |
int inside_dict = 0; |
int inside_dict = 0; |
Line 667 xmlDictFree(xmlDictPtr dict) {
|
Line 769 xmlDictFree(xmlDictPtr dict) {
|
return; |
return; |
|
|
if (!xmlDictInitialized) |
if (!xmlDictInitialized) |
if (!xmlInitializeDict()) | if (!__xmlInitializeDict()) |
return; |
return; |
|
|
/* decrement the counter, it may be shared by a parser and docs */ |
/* decrement the counter, it may be shared by a parser and docs */ |
Line 726 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
Line 828 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
xmlDictEntryPtr entry; |
xmlDictEntryPtr entry; |
xmlDictEntryPtr insert; |
xmlDictEntryPtr insert; |
const xmlChar *ret; |
const xmlChar *ret; |
|
unsigned int l; |
|
|
if ((dict == NULL) || (name == NULL)) |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
return(NULL); |
|
|
if (len < 0) |
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. |
* Check for duplicate and insertion location. |
*/ |
*/ |
okey = xmlDictComputeKey(dict, name, len); | okey = xmlDictComputeKey(dict, name, l); |
key = okey % dict->size; |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
insert = NULL; |
Line 744 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
Line 853 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
for (insert = &(dict->dict[key]); insert->next != NULL; |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
insert = insert->next) { |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((insert->okey == okey) && (insert->len == len)) { | if ((insert->okey == okey) && (insert->len == l)) { |
if (!memcmp(insert->name, name, len)) | if (!memcmp(insert->name, name, l)) |
return(insert->name); |
return(insert->name); |
} |
} |
#else |
#else |
if ((insert->okey == okey) && (insert->len == len) && | if ((insert->okey == okey) && (insert->len == l) && |
(!xmlStrncmp(insert->name, name, len))) | (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
return(insert->name); |
#endif |
#endif |
nbi++; |
nbi++; |
} |
} |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((insert->okey == okey) && (insert->len == len)) { | if ((insert->okey == okey) && (insert->len == l)) { |
if (!memcmp(insert->name, name, len)) | if (!memcmp(insert->name, name, l)) |
return(insert->name); |
return(insert->name); |
} |
} |
#else |
#else |
if ((insert->okey == okey) && (insert->len == len) && | if ((insert->okey == okey) && (insert->len == l) && |
(!xmlStrncmp(insert->name, name, len))) | (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
return(insert->name); |
#endif |
#endif |
} |
} |
Line 775 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
Line 884 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
(dict->subdict->size != MIN_DICT_SIZE)) || |
(dict->subdict->size != MIN_DICT_SIZE)) || |
((dict->size != MIN_DICT_SIZE) && |
((dict->size != MIN_DICT_SIZE) && |
(dict->subdict->size == MIN_DICT_SIZE))) |
(dict->subdict->size == MIN_DICT_SIZE))) |
skey = xmlDictComputeKey(dict->subdict, name, len); | skey = xmlDictComputeKey(dict->subdict, name, l); |
else |
else |
skey = okey; |
skey = okey; |
|
|
Line 786 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
Line 895 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
tmp = tmp->next) { |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((tmp->okey == skey) && (tmp->len == len)) { | if ((tmp->okey == skey) && (tmp->len == l)) { |
if (!memcmp(tmp->name, name, len)) | if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
return(tmp->name); |
} |
} |
#else |
#else |
if ((tmp->okey == skey) && (tmp->len == len) && | if ((tmp->okey == skey) && (tmp->len == l) && |
(!xmlStrncmp(tmp->name, name, len))) | (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
return(tmp->name); |
#endif |
#endif |
nbi++; |
nbi++; |
} |
} |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((tmp->okey == skey) && (tmp->len == len)) { | if ((tmp->okey == skey) && (tmp->len == l)) { |
if (!memcmp(tmp->name, name, len)) | if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
return(tmp->name); |
} |
} |
#else |
#else |
if ((tmp->okey == skey) && (tmp->len == len) && | if ((tmp->okey == skey) && (tmp->len == l) && |
(!xmlStrncmp(tmp->name, name, len))) | (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
return(tmp->name); |
#endif |
#endif |
} |
} |
key = okey % dict->size; |
key = okey % dict->size; |
} |
} |
|
|
ret = xmlDictAddString(dict, name, len); | ret = xmlDictAddString(dict, name, l); |
if (ret == NULL) |
if (ret == NULL) |
return(NULL); |
return(NULL); |
if (insert == NULL) { |
if (insert == NULL) { |
Line 822 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
Line 931 xmlDictLookup(xmlDictPtr dict, const xmlChar *name, in
|
return(NULL); |
return(NULL); |
} |
} |
entry->name = ret; |
entry->name = ret; |
entry->len = len; | entry->len = l; |
entry->next = NULL; |
entry->next = NULL; |
entry->valid = 1; |
entry->valid = 1; |
entry->okey = okey; |
entry->okey = okey; |
|
|
|
|
if (insert != NULL) | if (insert != NULL) |
insert->next = entry; |
insert->next = entry; |
|
|
dict->nbElems++; |
dict->nbElems++; |
Line 857 const xmlChar *
|
Line 966 const xmlChar *
|
xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
unsigned long key, okey, nbi = 0; |
unsigned long key, okey, nbi = 0; |
xmlDictEntryPtr insert; |
xmlDictEntryPtr insert; |
|
unsigned int l; |
|
|
if ((dict == NULL) || (name == NULL)) |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
return(NULL); |
|
|
if (len < 0) |
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. |
* Check for duplicate and insertion location. |
*/ |
*/ |
okey = xmlDictComputeKey(dict, name, len); | okey = xmlDictComputeKey(dict, name, l); |
key = okey % dict->size; |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
insert = NULL; |
Line 875 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
Line 990 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
for (insert = &(dict->dict[key]); insert->next != NULL; |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
insert = insert->next) { |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((insert->okey == okey) && (insert->len == len)) { | if ((insert->okey == okey) && (insert->len == l)) { |
if (!memcmp(insert->name, name, len)) | if (!memcmp(insert->name, name, l)) |
return(insert->name); |
return(insert->name); |
} |
} |
#else |
#else |
if ((insert->okey == okey) && (insert->len == len) && | if ((insert->okey == okey) && (insert->len == l) && |
(!xmlStrncmp(insert->name, name, len))) | (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
return(insert->name); |
#endif |
#endif |
nbi++; |
nbi++; |
} |
} |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((insert->okey == okey) && (insert->len == len)) { | if ((insert->okey == okey) && (insert->len == l)) { |
if (!memcmp(insert->name, name, len)) | if (!memcmp(insert->name, name, l)) |
return(insert->name); |
return(insert->name); |
} |
} |
#else |
#else |
if ((insert->okey == okey) && (insert->len == len) && | if ((insert->okey == okey) && (insert->len == l) && |
(!xmlStrncmp(insert->name, name, len))) | (!xmlStrncmp(insert->name, name, l))) |
return(insert->name); |
return(insert->name); |
#endif |
#endif |
} |
} |
Line 906 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
Line 1021 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
(dict->subdict->size != MIN_DICT_SIZE)) || |
(dict->subdict->size != MIN_DICT_SIZE)) || |
((dict->size != MIN_DICT_SIZE) && |
((dict->size != MIN_DICT_SIZE) && |
(dict->subdict->size == MIN_DICT_SIZE))) |
(dict->subdict->size == MIN_DICT_SIZE))) |
skey = xmlDictComputeKey(dict->subdict, name, len); | skey = xmlDictComputeKey(dict->subdict, name, l); |
else |
else |
skey = okey; |
skey = okey; |
|
|
Line 917 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
Line 1032 xmlDictExists(xmlDictPtr dict, const xmlChar *name, in
|
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
tmp = tmp->next) { |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((tmp->okey == skey) && (tmp->len == len)) { | if ((tmp->okey == skey) && (tmp->len == l)) { |
if (!memcmp(tmp->name, name, len)) | if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
return(tmp->name); |
} |
} |
#else |
#else |
if ((tmp->okey == skey) && (tmp->len == len) && | if ((tmp->okey == skey) && (tmp->len == l) && |
(!xmlStrncmp(tmp->name, name, len))) | (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
return(tmp->name); |
#endif |
#endif |
nbi++; |
nbi++; |
} |
} |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
if ((tmp->okey == skey) && (tmp->len == len)) { | if ((tmp->okey == skey) && (tmp->len == l)) { |
if (!memcmp(tmp->name, name, len)) | if (!memcmp(tmp->name, name, l)) |
return(tmp->name); |
return(tmp->name); |
} |
} |
#else |
#else |
if ((tmp->okey == skey) && (tmp->len == len) && | if ((tmp->okey == skey) && (tmp->len == l) && |
(!xmlStrncmp(tmp->name, name, len))) | (!xmlStrncmp(tmp->name, name, l))) |
return(tmp->name); |
return(tmp->name); |
#endif |
#endif |
} |
} |
Line 961 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix,
|
Line 1076 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix,
|
xmlDictEntryPtr entry; |
xmlDictEntryPtr entry; |
xmlDictEntryPtr insert; |
xmlDictEntryPtr insert; |
const xmlChar *ret; |
const xmlChar *ret; |
int len, plen, l; | unsigned int len, plen, l; |
|
|
if ((dict == NULL) || (name == NULL)) |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
return(NULL); |
Line 1037 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix,
|
Line 1152 xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix,
|
entry->valid = 1; |
entry->valid = 1; |
entry->okey = okey; |
entry->okey = okey; |
|
|
if (insert != NULL) | if (insert != NULL) |
insert->next = entry; |
insert->next = entry; |
|
|
dict->nbElems++; |
dict->nbElems++; |
Line 1095 xmlDictSize(xmlDictPtr dict) {
|
Line 1210 xmlDictSize(xmlDictPtr dict) {
|
return(dict->nbElems); |
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 |
#define bottom_dict |
#include "elfgcchack.h" |
#include "elfgcchack.h" |