| Index: third_party/libxml/src/hash.c
|
| diff --git a/third_party/libxml/src/hash.c b/third_party/libxml/src/hash.c
|
| index b78bc2d4e0038c35be0768f56d2efdbe22e43e3c..f9a201722445f17a297414fc222106b0ea40f39f 100644
|
| --- a/third_party/libxml/src/hash.c
|
| +++ b/third_party/libxml/src/hash.c
|
| @@ -3,7 +3,7 @@
|
| *
|
| * Reference: Your favorite introductory book on algorithms
|
| *
|
| - * Copyright (C) 2000 Bjorn Reese and Daniel Veillard.
|
| + * Copyright (C) 2000,2012 Bjorn Reese and 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
|
| @@ -21,6 +21,22 @@
|
| #include "libxml.h"
|
|
|
| #include <string.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
|
| + */
|
| +#if defined(HAVE_RAND) && defined(HAVE_SRAND) && defined(HAVE_TIME)
|
| +#define HASH_RANDOMIZATION
|
| +#endif
|
| +
|
| #include <libxml/parser.h>
|
| #include <libxml/hash.h>
|
| #include <libxml/xmlmemory.h>
|
| @@ -53,6 +69,9 @@ struct _xmlHashTable {
|
| int size;
|
| int nbElems;
|
| xmlDictPtr dict;
|
| +#ifdef HASH_RANDOMIZATION
|
| + int random_seed;
|
| +#endif
|
| };
|
|
|
| /*
|
| @@ -64,18 +83,23 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
| const xmlChar *name2, const xmlChar *name3) {
|
| unsigned long value = 0L;
|
| char ch;
|
| -
|
| +
|
| +#ifdef HASH_RANDOMIZATION
|
| + value = table->random_seed;
|
| +#endif
|
| if (name != NULL) {
|
| value += 30 * (*name);
|
| while ((ch = *name++) != 0) {
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| }
|
| }
|
| + value = value ^ ((value << 5) + (value >> 3));
|
| if (name2 != NULL) {
|
| while ((ch = *name2++) != 0) {
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| }
|
| }
|
| + value = value ^ ((value << 5) + (value >> 3));
|
| if (name3 != NULL) {
|
| while ((ch = *name3++) != 0) {
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| @@ -91,7 +115,10 @@ xmlHashComputeQKey(xmlHashTablePtr table,
|
| const xmlChar *prefix3, const xmlChar *name3) {
|
| unsigned long value = 0L;
|
| char ch;
|
| -
|
| +
|
| +#ifdef HASH_RANDOMIZATION
|
| + value = table->random_seed;
|
| +#endif
|
| if (prefix != NULL)
|
| value += 30 * (*prefix);
|
| else
|
| @@ -108,6 +135,7 @@ xmlHashComputeQKey(xmlHashTablePtr table,
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| }
|
| }
|
| + value = value ^ ((value << 5) + (value >> 3));
|
| if (prefix2 != NULL) {
|
| while ((ch = *prefix2++) != 0) {
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| @@ -119,6 +147,7 @@ xmlHashComputeQKey(xmlHashTablePtr table,
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| }
|
| }
|
| + value = value ^ ((value << 5) + (value >> 3));
|
| if (prefix3 != NULL) {
|
| while ((ch = *prefix3++) != 0) {
|
| value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
|
| @@ -144,10 +173,10 @@ xmlHashComputeQKey(xmlHashTablePtr table,
|
| xmlHashTablePtr
|
| xmlHashCreate(int size) {
|
| xmlHashTablePtr table;
|
| -
|
| +
|
| if (size <= 0)
|
| size = 256;
|
| -
|
| +
|
| table = xmlMalloc(sizeof(xmlHashTable));
|
| if (table) {
|
| table->dict = NULL;
|
| @@ -155,8 +184,11 @@ xmlHashCreate(int size) {
|
| table->nbElems = 0;
|
| table->table = xmlMalloc(size * sizeof(xmlHashEntry));
|
| if (table->table) {
|
| - memset(table->table, 0, size * sizeof(xmlHashEntry));
|
| - return(table);
|
| + memset(table->table, 0, size * sizeof(xmlHashEntry));
|
| +#ifdef HASH_RANDOMIZATION
|
| + table->random_seed = __xmlRandom();
|
| +#endif
|
| + return(table);
|
| }
|
| xmlFree(table);
|
| }
|
| @@ -202,7 +234,7 @@ xmlHashGrow(xmlHashTablePtr table, int size) {
|
| #ifdef DEBUG_GROW
|
| unsigned long nbElem = 0;
|
| #endif
|
| -
|
| +
|
| if (table == NULL)
|
| return(-1);
|
| if (size < 8)
|
| @@ -214,7 +246,7 @@ xmlHashGrow(xmlHashTablePtr table, int size) {
|
| oldtable = table->table;
|
| if (oldtable == NULL)
|
| return(-1);
|
| -
|
| +
|
| table->table = xmlMalloc(size * sizeof(xmlHashEntry));
|
| if (table->table == NULL) {
|
| table->table = oldtable;
|
| @@ -224,13 +256,13 @@ xmlHashGrow(xmlHashTablePtr table, int size) {
|
| table->size = size;
|
|
|
| /* If the two loops are merged, there would be situations where
|
| - a new entry needs to allocated and data copied into it from
|
| + a new entry needs to allocated and data copied into it from
|
| the main table. So instead, we run through the array twice, first
|
| copying all the elements in the main array (where we can't get
|
| conflicts) and then the rest, so we only free (and don't allocate)
|
| */
|
| for (i = 0; i < oldsize; i++) {
|
| - if (oldtable[i].valid == 0)
|
| + if (oldtable[i].valid == 0)
|
| continue;
|
| key = xmlHashComputeKey(table, oldtable[i].name, oldtable[i].name2,
|
| oldtable[i].name3);
|
| @@ -254,8 +286,8 @@ xmlHashGrow(xmlHashTablePtr table, int size) {
|
| table->table[key].next = NULL;
|
| xmlFree(iter);
|
| } else {
|
| - iter->next = table->table[key].next;
|
| - table->table[key].next = iter;
|
| + iter->next = table->table[key].next;
|
| + table->table[key].next = iter;
|
| }
|
|
|
| #ifdef DEBUG_GROW
|
| @@ -571,7 +603,7 @@ xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name,
|
| entry->valid = 1;
|
|
|
|
|
| - if (insert != NULL)
|
| + if (insert != NULL)
|
| insert->next = entry;
|
|
|
| table->nbElems++;
|
| @@ -720,7 +752,7 @@ xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name,
|
| * Returns the a pointer to the userdata
|
| */
|
| void *
|
| -xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
|
| +xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name,
|
| const xmlChar *name2, const xmlChar *name3) {
|
| unsigned long key;
|
| xmlHashEntryPtr entry;
|
| @@ -793,14 +825,14 @@ typedef struct {
|
| void *data;
|
| } stubData;
|
|
|
| -static void
|
| -stubHashScannerFull (void *payload, void *data, const xmlChar *name,
|
| +static void
|
| +stubHashScannerFull (void *payload, void *data, const xmlChar *name,
|
| const xmlChar *name2 ATTRIBUTE_UNUSED,
|
| const xmlChar *name3 ATTRIBUTE_UNUSED) {
|
| stubData *stubdata = (stubData *) data;
|
| stubdata->hashscanner (payload, stubdata->data, (xmlChar *) name);
|
| -}
|
| -
|
| +}
|
| +
|
| /**
|
| * xmlHashScan:
|
| * @table: the hash table
|
| @@ -813,7 +845,7 @@ void
|
| xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data) {
|
| stubData stubdata;
|
| stubdata.data = data;
|
| - stubdata.hashscanner = f;
|
| + stubdata.hashscanner = f;
|
| xmlHashScanFull (table, stubHashScannerFull, &stubdata);
|
| }
|
|
|
| @@ -838,7 +870,7 @@ xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
|
|
|
| if (table->table) {
|
| for(i = 0; i < table->size; i++) {
|
| - if (table->table[i].valid == 0)
|
| + if (table->table[i].valid == 0)
|
| continue;
|
| iter = &(table->table[i]);
|
| while (iter) {
|
| @@ -877,7 +909,7 @@ xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data) {
|
| * the comparison is considered to match.
|
| */
|
| void
|
| -xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
|
| +xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
|
| const xmlChar *name2, const xmlChar *name3,
|
| xmlHashScanner f, void *data) {
|
| xmlHashScanFull3 (table, name, name2, name3,
|
| @@ -898,7 +930,7 @@ xmlHashScan3(xmlHashTablePtr table, const xmlChar *name,
|
| * the comparison is considered to match.
|
| */
|
| void
|
| -xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
|
| +xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name,
|
| const xmlChar *name2, const xmlChar *name3,
|
| xmlHashScannerFull f, void *data) {
|
| int i;
|
| @@ -952,6 +984,9 @@ xmlHashCopy(xmlHashTablePtr table, xmlHashCopier f) {
|
| return(NULL);
|
|
|
| ret = xmlHashCreate(table->size);
|
| + if (ret == NULL)
|
| + return(NULL);
|
| +
|
| if (table->table) {
|
| for(i = 0; i < table->size; i++) {
|
| if (table->table[i].valid == 0)
|
|
|