]> granicus.if.org Git - php/commitdiff
Fixed bug #28072 (static array with some constant keys will be incorrectly ordered).
authorDmitry Stogov <dmitry@php.net>
Thu, 7 Jul 2005 15:16:57 +0000 (15:16 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 7 Jul 2005 15:16:57 +0000 (15:16 +0000)
NEWS
Zend/tests/bug28072.phpt [new file with mode: 0755]
Zend/zend_execute_API.c
Zend/zend_hash.c
Zend/zend_hash.h

diff --git a/NEWS b/NEWS
index a6e4c98fc01eadbded14ae9866fce1b326a62764..20aee85b3d8a2575846b92ceec9a0653098d1e74 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,8 @@ PHP                                                                        NEWS
 - Fixed bug #30096 (gmmktime does not return the corrent time). (Derick)
 - Fixed bug #30052 (Crash on shutdown after odbc_pconnect()). (Edin)
 - Fixed bug #28377 (debug_backtrace is intermittently passing args). (Dmitry)
+- Fixed bug #28072 (static array with some constant keys will be incorrectly
+  ordered). (Dmitry)
 - Fixed bug #27268 (Bad references accentuated by clone). (Dmitry)
 
 22 Jun 2005, PHP 5.1 Beta 2
diff --git a/Zend/tests/bug28072.phpt b/Zend/tests/bug28072.phpt
new file mode 100755 (executable)
index 0000000..7959a1c
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+Bug #28072 (static array with some constant keys will be incorrectly ordered)
+--FILE--
+<?php
+define("FIRST_KEY", "a");
+define("THIRD_KEY", "c");
+                                                                        
+                 
+function test()
+{
+        static $arr = array(
+                FIRST_KEY => "111",
+                "b" => "222",
+                THIRD_KEY => "333",
+                "d" => "444"
+        );
+        print_r($arr);
+}
+                                                                        
+function test2()
+{
+        static $arr = array(
+                FIRST_KEY => "111",
+                "a" => "222",
+                "c" => "333",
+                THIRD_KEY => "444"
+        );
+        print_r($arr);
+}
+                 
+test();
+test2();
+?>
+--EXPECT--
+Array
+(
+    [a] => 111
+    [b] => 222
+    [c] => 333
+    [d] => 444
+)
+Array
+(
+    [a] => 111
+    [c] => 444
+)
index 5272718ddc90de27aeedd662087e8aef10a3c946..adda863112abacacd3ea31f8cd039c263e4ef3b4 100644 (file)
@@ -490,17 +490,33 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
 
                        /* preserve this bit for inheritance */
                        Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
+                       zval_ptr_dtor(element);
+                       *element = new_val;
 
                        switch (const_value.type) {
-                               case IS_STRING:
-                                       zend_symtable_update(p->value.ht, const_value.value.str.val, const_value.value.str.len+1, &new_val, sizeof(zval *), NULL);
+                               case IS_STRING: {
+                                       long lval;
+                                       double dval;
+
+                                       if (is_numeric_string(const_value.value.str.val, const_value.value.str.len, &lval, &dval, 0) == IS_LONG) {
+                                               zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
+                                       } else {
+                                               zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, const_value.value.str.val, const_value.value.str.len+1, 0);
+                                       }
                                        break;
+                               }
                                case IS_BOOL:
                                case IS_LONG:
-                                       zend_hash_index_update(p->value.ht, const_value.value.lval, &new_val, sizeof(zval *), NULL);
+                                       zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, const_value.value.lval);
+                                       break;
+                               case IS_DOUBLE:
+                                       zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, (long)const_value.value.dval);
+                                       break;
+                               case IS_NULL:
+                                       zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, "", 1, 0);
                                        break;
                        }
-                       zend_hash_del(p->value.ht, str_index, str_index_len);
+                       zend_hash_move_forward(p->value.ht);
                        zval_dtor(&const_value);
                }
                zend_hash_apply_with_argument(p->value.ht, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
index ec75fb6446ee87821a66a1fde6b49baac9e768f1..9d78e54392b4e5670e217991a15190669abe8e34 100644 (file)
@@ -1106,6 +1106,93 @@ 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, char *str_index, uint str_length, ulong num_index, HashPosition *pos)
+{
+       Bucket *p;
+
+       p = pos ? (*pos) : ht->pInternalPointer;
+
+       IS_CONSISTENT(ht);
+
+       if (p) {
+               if (key_type == HASH_KEY_IS_LONG) {
+                       str_length = 0;
+                       if (!p->nKeyLength && p->h == num_index) {
+                               return SUCCESS;
+                       }
+                       zend_hash_index_del(ht, num_index);
+               } else if (key_type == HASH_KEY_IS_STRING) {
+                       if (p->nKeyLength == str_length &&
+                           memcmp(p->arKey, str_index, str_length) == 0) {
+                               return SUCCESS;
+                       }
+                       zend_hash_del(ht, str_index, str_length);
+               } else {
+                       return FAILURE;
+               }
+
+               HANDLE_BLOCK_INTERRUPTIONS();
+
+               if (p->pNext) {
+                       p->pNext->pLast = p->pLast;
+               }
+               if (p->pLast) {
+                       p->pLast->pNext = p->pNext;
+               } else{
+                       ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
+               }
+
+               if (p->nKeyLength != str_length) {
+                       Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent);
+
+                       q->nKeyLength = str_length;
+                       if (p->pData == &p->pDataPtr) {
+                               q->pData = &q->pDataPtr;
+                       } else {
+                               q->pData = p->pData;
+                       }
+                       q->pDataPtr = p->pDataPtr;
+                       q->pListNext = p->pListNext;
+                       q->pListLast = p->pListLast;
+                       if (q->pListNext) {
+                               p->pListNext->pListLast = q;
+                       } else {
+                               ht->pListTail = q;
+                       }
+                       if (q->pListLast) {
+                               p->pListLast->pListNext = q;
+                       } else {
+                               ht->pListHead = q;
+                       }
+                       if (ht->pInternalPointer == p) {
+                               ht->pInternalPointer = q;
+                       }
+                       if (pos) {
+                               *pos = q;
+                       }
+                       pefree(p, ht->persistent);
+                       p = q;
+               }
+
+               if (key_type == HASH_KEY_IS_LONG) {
+                       p->h = num_index;
+               } else {
+                       memcpy(p->arKey, str_index, str_length);
+                       p->h = zend_inline_hash_func(str_index, str_length);
+               }
+
+               CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
+               ht->arBuckets[p->h & ht->nTableMask] = p;
+               HANDLE_UNBLOCK_INTERRUPTIONS();
+
+               return SUCCESS;
+       } else {
+               return FAILURE;
+       }
+}
 
 ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
                                                        compare_func_t compar, int renumber TSRMLS_DC)
index 0b6dbb82887d36f67cd0ad6985dba5c7dc324831..292f9747f48263b1f5c0af7313b0f96c537ec95f 100644 (file)
@@ -174,6 +174,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, char *str_index, uint str_length, ulong num_index, HashPosition *pos);
 
 #define zend_hash_has_more_elements(ht) \
        zend_hash_has_more_elements_ex(ht, NULL)
@@ -191,6 +192,8 @@ ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos
        zend_hash_internal_pointer_reset_ex(ht, NULL)
 #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)
 
 /* Copying, merging and sorting */
 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);