]> granicus.if.org Git - php/commitdiff
Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate...
authorDmitry Stogov <dmitry@php.net>
Fri, 1 Aug 2008 14:21:46 +0000 (14:21 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 1 Aug 2008 14:21:46 +0000 (14:21 +0000)
Zend/tests/bug28072.phpt
Zend/zend_execute_API.c
Zend/zend_hash.c
Zend/zend_hash.h

index 7959a1c4da4dc58c69430225d20264bcae16f02f..76208733f8111844961994e215c4d868b41ea0ac 100755 (executable)
@@ -41,6 +41,6 @@ Array
 )
 Array
 (
-    [a] => 111
+    [a] => 222
     [c] => 444
 )
index 8dc24e269d499fb2af9803924545f2242756d4a0..ce63cabcf7fb738b2cf18e97a02a7a4d56f24a98 100644 (file)
@@ -654,17 +654,17 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
                        switch (Z_TYPE(const_value)) {
                                case IS_STRING:
                                case IS_UNICODE:
-                                       zend_u_symtable_update_current_key(Z_ARRVAL_P(p), Z_TYPE(const_value), Z_UNIVAL(const_value), Z_UNILEN(const_value) + 1);
+                                       zend_u_symtable_update_current_key(Z_ARRVAL_P(p), Z_TYPE(const_value), Z_UNIVAL(const_value), Z_UNILEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
                                        break;
                                case IS_BOOL:
                                case IS_LONG:
-                                       zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, Z_LVAL(const_value));
+                                       zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
                                        break;
                                case IS_DOUBLE:
-                                       zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, (long)Z_DVAL(const_value));
+                                       zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, (long)Z_DVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
                                        break;
                                case IS_NULL:
-                                       zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, EMPTY_ZSTR, 1, 0);
+                                       zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, EMPTY_ZSTR, 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
                                        break;
                        }
                        zend_hash_move_forward(Z_ARRVAL_P(p));
index bd650195b8a75fc2b61071f2bf75471f90b515b2..67d0588839dd4165a0ab9d7df288889aca07b3be 100644 (file)
@@ -1646,7 +1646,7 @@ ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosi
 /* This function changes key of currevt element without changing elements'
  * order. If element with target key already exists, it will be deleted first.
  */
-ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, HashPosition *pos) /* {{{ */
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, int mode, HashPosition *pos) /* {{{ */
 {
        Bucket *p;
        uint real_length;
@@ -1661,23 +1661,77 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr s
                        if (!p->nKeyLength && p->h == num_index) {
                                return SUCCESS;
                        }
+
+                       if (mode != HASH_UPDATE_KEY_ANYWAY) {
+                               Bucket *q = ht->arBuckets[num_index & ht->nTableMask];
+                               int found = 0;
+
+                               while (q != NULL) {
+                                       if (q == p) {
+                                               found = 1;
+                                       } else if (!q->nKeyLength && q->h == num_index) {
+                                           if (found) {
+                                               if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
+                                                       break;
+                                               } else {
+                                                               zend_hash_index_del(ht, p->h);
+                                                       return FAILURE;
+                                               }
+                                           } else {
+                                               if (mode & HASH_UPDATE_KEY_IF_AFTER) {
+                                                       break;
+                                               } else {
+                                                               zend_hash_index_del(ht, p->h);
+                                                       return FAILURE;
+                                               }
+                                               }
+                                       }
+                                       q = q->pNext;
+                               }
+                       }
+
                        zend_hash_index_del(ht, num_index);
-               } else if (key_type == HASH_KEY_IS_STRING) {
-                       real_length = str_length;
+               } else if (key_type == HASH_KEY_IS_STRING ||
+                          key_type == HASH_KEY_IS_UNICODE) {
+                       real_length = key_type == HASH_KEY_IS_STRING ? str_length : str_length * sizeof(UChar);
                        if (p->nKeyLength == str_length &&
-                           p->key.type == IS_STRING &&
-                           memcmp(p->key.arKey.s, str_index.s, str_length) == 0) {
+                           p->key.type == key_type &&
+                           memcmp(p->key.arKey.s, str_index.v, real_length) == 0) {
                                return SUCCESS;
                        }
-                       zend_u_hash_del(ht, IS_STRING, str_index, str_length);
-               } else if (key_type == HASH_KEY_IS_UNICODE) {
-                       real_length = str_length * sizeof(UChar);
-                       if (p->nKeyLength == str_length &&
-                           p->key.type == IS_UNICODE &&
-                           memcmp(p->key.arKey.u, str_index.u, real_length) == 0) {
-                               return SUCCESS;
+
+                       if (mode != HASH_UPDATE_KEY_ANYWAY) {
+                               ulong h = zend_u_inline_hash_func(key_type, str_index, str_length);
+                               Bucket *q = ht->arBuckets[h & ht->nTableMask];
+                               int found = 0;
+
+                               while (q != NULL) {
+                                       if (q == p) {
+                                               found = 1;
+                                       } else if (q->h == h && q->nKeyLength == str_length && 
+                                                  q->key.type == key_type &&
+                                                  memcmp(q->key.arKey.s, str_index.v, real_length) == 0) {
+                                           if (found) {
+                                               if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
+                                                       break;
+                                               } else {
+                                                               zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
+                                                       return FAILURE;
+                                               }
+                                           } else {
+                                               if (mode & HASH_UPDATE_KEY_IF_AFTER) {
+                                                       break;
+                                               } else {
+                                                               zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
+                                                       return FAILURE;
+                                               }
+                                               }
+                                       }
+                                       q = q->pNext;
+                               }
                        }
-                       zend_u_hash_del(ht, IS_UNICODE, str_index, str_length);
+
+                       zend_u_hash_del(ht, key_type, str_index, str_length);
                } else {
                        return FAILURE;
                }
@@ -1977,18 +2031,18 @@ ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, zstr arKey,
 }
 /* }}} */
 
-ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
+ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, int mode) /* {{{ */
 {
        zend_uchar key_type;
 
        if (type == IS_STRING) {
                key_type = HASH_KEY_IS_STRING;
-               ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
+               ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
        } else {
                key_type = HASH_KEY_IS_UNICODE;
-               ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
+               ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
        }
-       return zend_hash_update_current_key(ht, key_type, arKey, nKeyLength, 0);
+       return zend_hash_update_current_key_ex(ht, key_type, arKey, nKeyLength, 0, mode, NULL);
 }
 /* }}} */
 
@@ -2020,10 +2074,10 @@ ZEND_API int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLen
 }
 /* }}} */
 
-ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
+ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength, int mode) /* {{{ */
 {
-       ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
-       return zend_hash_update_current_key(ht, HASH_KEY_IS_STRING, ZSTR(arKey), nKeyLength, 0);
+       ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
+       return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, ZSTR(arKey), nKeyLength, 0, mode, NULL);
 }
 /* }}} */
 
index 6da6c4e322f7e2ec84ed2762b5483f4f48870021..9cb1e54638a49a74a90f1c7e323ece0479f8db87 100644 (file)
 #define HASH_DEL_INDEX 1
 #define HASH_DEL_KEY_QUICK 2
 
-
+#define HASH_UPDATE_KEY_IF_NONE    0
+#define HASH_UPDATE_KEY_IF_BEFORE  1
+#define HASH_UPDATE_KEY_IF_AFTER   2
+#define HASH_UPDATE_KEY_ANYWAY     3
 
 typedef ulong (*hash_func_t)(const char *arKey, uint nKeyLength);
 typedef int  (*compare_func_t)(const void *, const void * TSRMLS_DC);
@@ -240,7 +243,7 @@ ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
 ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
 ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
 ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
-ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, HashPosition *pos);
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, int mode, HashPosition *pos);
 
 typedef struct _HashPointer {
        HashPosition pos;
@@ -267,7 +270,7 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr);
 #define zend_hash_internal_pointer_end(ht) \
        zend_hash_internal_pointer_end_ex(ht, NULL)
 #define zend_hash_update_current_key(ht, key_type, str_index, str_length, num_index) \
-       zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, NULL)
+       zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, HASH_UPDATE_KEY_ANYWAY, NULL)
 
 /* Copying, merging and sorting */
 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
@@ -371,7 +374,7 @@ ZEND_API int zend_symtable_update(HashTable *ht, const char *arKey, uint nKeyLen
 ZEND_API int zend_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength);
 ZEND_API int zend_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
 ZEND_API int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength);
-ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength);
+ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength, int mode);
 
 ZEND_API int zend_ascii_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
 ZEND_API int zend_ascii_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength);
@@ -392,7 +395,7 @@ ZEND_API int zend_u_symtable_update(HashTable *ht, zend_uchar type, zstr arKey,
 ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
 ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void **pData);
 ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
-ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
+ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, int mode);
 
 /* {{{ ZEND_HANDLE_*_NUMERIC macros */
 #define ZEND_HANDLE_NUMERIC(key, length, func) {                                                                               \