version 1.1, 2012/02/21 23:37:58
|
version 1.1.1.2, 2013/07/22 01:22:19
|
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" |
|
|
|
#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 66 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 98 struct _xmlDict {
|
Line 120 struct _xmlDict {
|
xmlDictStringsPtr strings; |
xmlDictStringsPtr strings; |
|
|
struct _xmlDict *subdict; |
struct _xmlDict *subdict; |
|
/* used for randomization */ |
|
int seed; |
}; |
}; |
|
|
/* |
/* |
Line 111 static xmlRMutexPtr xmlDictMutex = NULL;
|
Line 135 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 |
|
*/ |
|
unsigned int rand_seed = 0; |
|
#endif |
|
#endif |
|
|
/** |
/** |
* xmlInitializeDict: |
* xmlInitializeDict: |
* |
* |
* Do the dictionary mutex initialization. |
* 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 |
* preferably be done once at startup |
|
* |
|
* 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 277 found_pool:
|
Line 342 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 375 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 411 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 446 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 460 xmlDictCreate(void) {
|
Line 525 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 556 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); |
} |
} |