]> granicus.if.org Git - php/commitdiff
Prevent HashTable compaction below HT_MIN_SIZE (this may lead to hash collisions).
authorDmitry Stogov <dmitry@zend.com>
Wed, 2 Sep 2015 10:03:31 +0000 (13:03 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 2 Sep 2015 10:03:31 +0000 (13:03 +0300)
ext/opcache/zend_persist.c
ext/opcache/zend_persist_calc.c

index dec68b7cd710cebfe2185806b01af5df32891731..8e37e6247b56b16a436bb5099aafd4567cb74161 100644 (file)
@@ -94,13 +94,15 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement
                /* compact table */
                void *old_data = HT_GET_DATA_ADDR(ht);
                Bucket *old_buckets = ht->arData;
-               int32_t hash_size = -(int32_t)ht->nTableMask;
+               int32_t hash_size;
 
-               while (hash_size >> 1 > ht->nNumUsed) {
-                       hash_size >>= 1;
-               }
-               if (hash_size < -HT_MIN_MASK) {
-                       hash_size = -HT_MIN_MASK;
+               if (ht->nNumUsed <= HT_MIN_SIZE) {
+                       hash_size = HT_MIN_SIZE;
+               } else {
+                       hash_size = -(int32_t)ht->nTableMask;
+                       while (hash_size >> 1 > ht->nNumUsed) {
+                               hash_size >>= 1;
+                       }
                }
                ht->nTableMask = -hash_size;
                ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
@@ -174,13 +176,15 @@ static void zend_hash_persist_immutable(HashTable *ht)
                /* compact table */
                void *old_data = HT_GET_DATA_ADDR(ht);
                Bucket *old_buckets = ht->arData;
-               int32_t hash_size = -(int32_t)ht->nTableMask;
+               int32_t hash_size;
 
-               while (hash_size >> 1 > ht->nNumUsed) {
-                       hash_size >>= 1;
-               }
-               if (hash_size < -HT_MIN_MASK) {
-                       hash_size = -HT_MIN_MASK;
+               if (ht->nNumUsed <= HT_MIN_SIZE) {
+                       hash_size = HT_MIN_SIZE;
+               } else {
+                       hash_size = -(int32_t)ht->nTableMask;
+                       while (hash_size >> 1 > ht->nNumUsed) {
+                               hash_size >>= 1;
+                       }
                }
                ht->nTableMask = -hash_size;
                ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
index 5217c2ca9e6b7e88c891fa2284d776f48964e13c..bad7d70cc8dfb64e73aafcda46cee0edcb4c5142 100644 (file)
@@ -65,8 +65,8 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *
                while (hash_size >> 1 > ht->nNumUsed) {
                        hash_size >>= 1;
                }
-               if (hash_size < -HT_MIN_MASK) {
-                       hash_size = -HT_MIN_MASK;
+               if (hash_size < HT_MIN_SIZE) {
+                       hash_size = HT_MIN_SIZE;
                }
                ADD_SIZE(hash_size * sizeof(uint32_t) + ht->nNumUsed * sizeof(Bucket));
        } else {