mirror of
https://github.com/php/php-src.git
synced 2025-01-19 02:03:47 +08:00
Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate keys).
This commit is contained in:
parent
4e5280a7a2
commit
37a769353f
2
NEWS
2
NEWS
@ -1,6 +1,8 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 200?, PHP 5.3.0 Alpha 2
|
||||
- Fixed bug #44100 (Inconsistent handling of static array declarations with
|
||||
duplicate keys). (Dmitry)
|
||||
|
||||
01 Aug 2008, PHP 5.3.0 Alpha 1
|
||||
- Upgraded bundled PCRE to version 7.7 (Nuno)
|
||||
|
@ -41,6 +41,6 @@ Array
|
||||
)
|
||||
Array
|
||||
(
|
||||
[a] => 111
|
||||
[a] => 222
|
||||
[c] => 444
|
||||
)
|
||||
|
@ -599,17 +599,17 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
|
||||
|
||||
switch (Z_TYPE(const_value)) {
|
||||
case IS_STRING:
|
||||
zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1);
|
||||
zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(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, 0, Z_LVAL(const_value));
|
||||
zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 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, 0, (long)Z_DVAL(const_value));
|
||||
zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 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, "", 1, 0);
|
||||
zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
|
||||
break;
|
||||
}
|
||||
zend_hash_move_forward(Z_ARRVAL_P(p));
|
||||
|
@ -1170,7 +1170,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, const char *str_index, uint str_length, ulong num_index, HashPosition *pos)
|
||||
ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos)
|
||||
{
|
||||
Bucket *p;
|
||||
|
||||
@ -1184,12 +1184,72 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
|
||||
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) {
|
||||
if (p->nKeyLength == str_length &&
|
||||
memcmp(p->arKey, str_index, str_length) == 0) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (mode != HASH_UPDATE_KEY_ANYWAY) {
|
||||
ulong h = zend_inline_hash_func(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 &&
|
||||
memcmp(q->arKey, str_index, str_length) == 0) {
|
||||
if (found) {
|
||||
if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
|
||||
break;
|
||||
} else {
|
||||
zend_hash_del(ht, p->arKey, p->nKeyLength);
|
||||
return FAILURE;
|
||||
}
|
||||
} else {
|
||||
if (mode & HASH_UPDATE_KEY_IF_AFTER) {
|
||||
break;
|
||||
} else {
|
||||
zend_hash_del(ht, p->arKey, p->nKeyLength);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
q = q->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
zend_hash_del(ht, str_index, str_length);
|
||||
} else {
|
||||
return FAILURE;
|
||||
|
@ -37,6 +37,11 @@
|
||||
#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);
|
||||
typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC);
|
||||
@ -124,7 +129,6 @@ ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint
|
||||
#define ZEND_HASH_APPLY_REMOVE 1<<0
|
||||
#define ZEND_HASH_APPLY_STOP 1<<1
|
||||
|
||||
|
||||
typedef int (*apply_func_t)(void *pDest TSRMLS_DC);
|
||||
typedef int (*apply_func_arg_t)(void *pDest, void *argument TSRMLS_DC);
|
||||
typedef int (*apply_func_args_t)(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
|
||||
@ -177,7 +181,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, const char *str_index, uint str_length, ulong num_index, HashPosition *pos);
|
||||
ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos);
|
||||
|
||||
typedef struct _HashPointer {
|
||||
HashPosition pos;
|
||||
@ -204,7 +208,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);
|
||||
@ -364,10 +368,10 @@ static inline int zend_symtable_exists(HashTable *ht, const char *arKey, uint nK
|
||||
return zend_hash_exists(ht, arKey, nKeyLength);
|
||||
}
|
||||
|
||||
static inline int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength)
|
||||
static inline 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, 0, idx));
|
||||
return zend_hash_update_current_key(ht, HASH_KEY_IS_STRING, arKey, nKeyLength, 0);
|
||||
ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL, 0, idx, mode, NULL));
|
||||
return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, arKey, nKeyLength, 0, mode, NULL);
|
||||
}
|
||||
|
||||
#endif /* ZEND_HASH_H */
|
||||
|
Loading…
Reference in New Issue
Block a user