Index: src/OFMapTable.h ================================================================== --- src/OFMapTable.h +++ src/OFMapTable.h @@ -49,10 +49,11 @@ of_map_table_functions_t keyFunctions, valueFunctions; struct of_map_table_bucket **buckets; uint32_t minCapacity, capacity, count; unsigned long mutations; uint32_t seed; + uint8_t rotate; } /*! * @brief Creates a new OFMapTable with the specified key and value functions. * Index: src/OFMapTable.m ================================================================== --- src/OFMapTable.m +++ src/OFMapTable.m @@ -151,12 +151,14 @@ buckets = [self allocMemoryWithSize: sizeof(*buckets) count: capacity]; memset(buckets, 0, capacity * sizeof(*buckets)); - if (of_hash_seed != 0) + if (of_hash_seed != 0) { seed = of_random(); + rotate = of_random() & 0x1F; + } } @catch (id e) { [self release]; @throw e; } @@ -230,11 +232,13 @@ for (i = 0; i < capacity; i++) if (buckets[i] != NULL && buckets[i] != &deleted) [copy OF_setValue: buckets[i]->value forKey: buckets[i]->key - hash: buckets[i]->hash ^ seed]; + hash: OF_ROR( + buckets[i]->hash ^ seed, + rotate)]; } @catch (id e) { [copy release]; @throw e; } @@ -255,11 +259,11 @@ if (key == NULL) @throw [OFInvalidArgumentException exceptionWithClass: [self class] selector: _cmd]; - hash = keyFunctions.hash(key) ^ seed; + hash = OF_ROL(keyFunctions.hash(key) ^ seed, rotate); last = capacity; for (i = hash & (capacity - 1); i < last && buckets[i] != NULL; i++) { if (buckets[i] == &deleted) continue; @@ -287,10 +291,11 @@ - (void)OF_resizeForCount: (uint32_t)newCount { uint32_t i, fullness, newCapacity, newSeed = 0, seedUpdate = 0; struct of_map_table_bucket **newBuckets; + uint8_t newRotate = 0; if (newCount > UINT32_MAX || newCount > UINT32_MAX / sizeof(*buckets) || newCount > UINT32_MAX / 8) @throw [OFOutOfRangeException exceptionWithClass: [self class]]; @@ -313,17 +318,21 @@ newBuckets[i] = NULL; if (of_hash_seed != 0) { newSeed = of_random(); seedUpdate = seed ^ newSeed; + + newRotate = of_random() & 0x1F; } for (i = 0; i < capacity; i++) { if (buckets[i] != NULL && buckets[i] != &deleted) { uint32_t j, last; - buckets[i]->hash ^= seedUpdate; + buckets[i]->hash = OF_ROL( + OF_ROR(buckets[i]->hash, rotate) ^ seedUpdate, + newRotate); last = newCapacity; j = buckets[i]->hash & (newCapacity - 1); for (; j < last && newBuckets[j] != NULL; j++); @@ -344,10 +353,11 @@ [self freeMemory: buckets]; buckets = newBuckets; capacity = newCapacity; seed = newSeed; + rotate = newRotate; } - (void)OF_setValue: (void*)value forKey: (void*)key hash: (uint32_t)hash @@ -359,11 +369,11 @@ @throw [OFInvalidArgumentException exceptionWithClass: [self class] selector: _cmd]; last = capacity; - seededHash = hash ^ seed; + seededHash = OF_ROL(hash ^ seed, rotate); for (i = seededHash & (capacity - 1); i < last && buckets[i] != NULL; i++) { if (buckets[i] == &deleted) continue; @@ -389,11 +399,11 @@ if (i >= last || buckets[i] == NULL || buckets[i] == &deleted || !keyFunctions.equal(buckets[i]->key, key)) { struct of_map_table_bucket *bucket; [self OF_resizeForCount: count + 1]; - seededHash = hash ^ seed; + seededHash = OF_ROL(hash ^ seed, rotate); mutations++; last = capacity; for (i = seededHash & (capacity - 1); i < last && @@ -456,11 +466,11 @@ if (key == NULL) @throw [OFInvalidArgumentException exceptionWithClass: [self class] selector: _cmd]; - hash = keyFunctions.hash(key) ^ seed; + hash = OF_ROL(keyFunctions.hash(key) ^ seed, rotate); last = capacity; for (i = hash & (capacity - 1); i < last && buckets[i] != NULL; i++) { if (buckets[i] == &deleted) continue; Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -323,10 +323,13 @@ #endif #define OF_ROL(value, bits) \ (((value) << ((bits) % (sizeof(value) * 8))) | \ (value) >> (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) +#define OF_ROR(value, bits) \ + (((value) >> ((bits) % (sizeof(value) * 8))) | \ + (value) << (sizeof(value) * 8 - ((bits) % (sizeof(value) * 8)))) #define OF_HASH_INIT(hash) hash = of_hash_seed #define OF_HASH_ADD(hash, byte) \ { \ hash += (uint8_t)(byte); \