From: Dmitry Stogov Date: Fri, 1 Aug 2008 14:21:46 +0000 (+0000) Subject: Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate... X-Git-Tag: BEFORE_HEAD_NS_CHANGE~921 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d93a86b4d263014b3c7d1509fb02fad0ba97b8d8;p=php Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate keys). --- diff --git a/Zend/tests/bug28072.phpt b/Zend/tests/bug28072.phpt index 7959a1c4da..76208733f8 100755 --- a/Zend/tests/bug28072.phpt +++ b/Zend/tests/bug28072.phpt @@ -41,6 +41,6 @@ Array ) Array ( - [a] => 111 + [a] => 222 [c] => 444 ) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 8dc24e269d..ce63cabcf7 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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)); diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index bd650195b8..67d0588839 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -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); } /* }}} */ diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 6da6c4e322..9cb1e54638 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -38,7 +38,10 @@ #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) { \