summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2005-07-07 15:16:57 +0000
committerDmitry Stogov <dmitry@php.net>2005-07-07 15:16:57 +0000
commitd9c1a380ad0b073c8750f130a412229aeaed9a1b (patch)
treec4df575424a1d4ebe3413ca22dbd4193d02eb62e /Zend
parent3c5b9a6e6a1cb7462c5e2ffec23bea34f29a18dd (diff)
downloadphp-git-d9c1a380ad0b073c8750f130a412229aeaed9a1b.tar.gz
Fixed bug #28072 (static array with some constant keys will be incorrectly ordered).
Diffstat (limited to 'Zend')
-rwxr-xr-xZend/tests/bug28072.phpt46
-rw-r--r--Zend/zend_execute_API.c24
-rw-r--r--Zend/zend_hash.c87
-rw-r--r--Zend/zend_hash.h3
4 files changed, 156 insertions, 4 deletions
diff --git a/Zend/tests/bug28072.phpt b/Zend/tests/bug28072.phpt
new file mode 100755
index 0000000000..7959a1c4da
--- /dev/null
+++ b/Zend/tests/bug28072.phpt
@@ -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
+)
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 5272718ddc..adda863112 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -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);
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index ec75fb6446..9d78e54392 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -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)
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 0b6dbb8288..292f9747f4 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -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);