Index: src/OFMapTable.m ================================================================== --- src/OFMapTable.m +++ src/OFMapTable.m @@ -137,18 +137,24 @@ SET_DEFAULT(_valueFunctions.hash, default_hash); SET_DEFAULT(_valueFunctions.equal, default_equal); #undef SET_DEFAULT - if (capacity > UINT32_MAX || - capacity > UINT32_MAX / sizeof(*_buckets) || + if (capacity > UINT32_MAX / sizeof(*_buckets) || capacity > UINT32_MAX / 8) @throw [OFOutOfRangeException exception]; - for (_capacity = 1; _capacity < capacity; _capacity *= 2); - if (capacity * 8 / _capacity >= 6) + for (_capacity = 1; _capacity < capacity;) { + if (_capacity > UINT32_MAX / 2) + @throw [OFOutOfRangeException exception]; + _capacity *= 2; + } + + if (capacity * 8 / _capacity >= 6) + if (_capacity <= UINT32_MAX / 2) + _capacity *= 2; if (_capacity < MIN_CAPACITY) _capacity = MIN_CAPACITY; _buckets = [self allocMemoryWithSize: sizeof(*_buckets) @@ -294,19 +300,21 @@ - (void)OF_resizeForCount: (uint32_t)count { uint32_t i, fullness, capacity; struct of_map_table_bucket **buckets; - if (count > UINT32_MAX || count > UINT32_MAX / sizeof(*_buckets) || - count > UINT32_MAX / 8) + if (count > UINT32_MAX / sizeof(*_buckets) || count > UINT32_MAX / 8) @throw [OFOutOfRangeException exception]; fullness = count * 8 / _capacity; - if (fullness >= 6) + if (fullness >= 6) { + if (_capacity > UINT32_MAX / 2) + return; + capacity = _capacity * 2; - else if (fullness <= 1) + } else if (fullness <= 1) capacity = _capacity / 2; else return; /* @@ -336,12 +344,10 @@ for (j = 0; j < last && buckets[j] != NULL; j++); } - assert(j < last); - buckets[j] = _buckets[i]; } } [self freeMemory: _buckets]; @@ -458,18 +464,19 @@ for (i = hash & (_capacity - 1); i < last && _buckets[i] != NULL; i++) { if (_buckets[i] == &deleted) continue; if (_keyFunctions.equal(_buckets[i]->key, key)) { + _mutations++; + _keyFunctions.release(_buckets[i]->key); _valueFunctions.release(_buckets[i]->value); [self freeMemory: _buckets[i]]; _buckets[i] = &deleted; _count--; - _mutations++; [self OF_resizeForCount: _count]; return; } }