Browse Source

Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate keys).

experimental/first_unicode_implementation
Dmitry Stogov 18 years ago
parent
commit
d93a86b4d2
  1. 2
      Zend/tests/bug28072.phpt
  2. 8
      Zend/zend_execute_API.c
  3. 94
      Zend/zend_hash.c
  4. 13
      Zend/zend_hash.h

2
Zend/tests/bug28072.phpt

@ -41,6 +41,6 @@ Array
)
Array
(
[a] => 111
[a] => 222
[c] => 444
)

8
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));

94
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);
}
/* }}} */

13
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) { \

Loading…
Cancel
Save