|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2013-11-26 06:08 UTC] to dot yashin at gmail dot com
Description:
------------
Can not access an array element by index after casting
Test script:
---------------
<?php
$object = new StdClass();
$object->{'1'} = 'test';
/**
* object(stdClass)#1 (1) {
* ["1"]=>
* string(4) "test"
* }
*/
$array = (array) $object;
/**
* array(1) {
* ["1"]=>
* string(4) "test"
* }
*/
var_dump($array[1]);
// NULL
var_dump($array['1']);
// NULL
Expected result:
----------------
var_dump($array['1']);
// 'test'
Actual result:
--------------
var_dump($array['1']);
// NULL
PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 22:00:01 2025 UTC |
This is pretty old bug as I know, I had nothing to do so I made a patch, but I doubt it will be merged because this use case is so rare... diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 96c3f3d..14381b9 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -810,13 +810,20 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR HASH_UNPROTECT_RECURSION(ht); } - -ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) +ZEND_API void zend_hash_copy_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int reindex_numeric_keys) { Bucket *p; void *new_entry; zend_bool setTargetPointer; + long *longKey; + double *doubleKey; + int keyType; + if (reindex_numeric_keys) { + longKey = emalloc(sizeof(long)); + doubleKey = emalloc(sizeof(double)); + } + IS_CONSISTENT(source); IS_CONSISTENT(target); @@ -826,11 +833,21 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun if (setTargetPointer && source->pInternalPointer == p) { target->pInternalPointer = NULL; } - if (p->nKeyLength) { + + if (p->nKeyLength && ( ! reindex_numeric_keys || + ! (keyType = is_numeric_string(p->arKey, p->nKeyLength, longKey, doubleKey, -1)))) { + zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &new_entry); - } else { + } else if ( ! p->nKeyLength) { zend_hash_index_update(target, p->h, p->pData, size, &new_entry); + } else { + if (keyType == IS_DOUBLE) { + *longKey = zend_dval_to_lval(*doubleKey); + } + + zend_hash_index_update(target, *longKey, p->pData, size, &new_entry); } + if (pCopyConstructor) { pCopyConstructor(new_entry); } @@ -841,6 +858,10 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun } } +ZEND_API inline void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) +{ + zend_hash_copy_ex(target, source, pCopyConstructor, tmp, size, 0); +} ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite ZEND_FILE_LINE_DC) { diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 5c84deb2..55ab2c2 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -709,7 +709,7 @@ ZEND_API void convert_to_array(zval *op) /* {{{ */ } else if (Z_OBJ_HT_P(op)->get_properties) { HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC); if (obj_ht) { - zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + zend_hash_copy_ex(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *), 1); } } else { convert_object_to_type(op, IS_ARRAY, convert_to_array);Maybe it should be prohibited to pass illegal names to ->{} operator? Pros: - Such names can't be accessed with -> operator anyway, so they have marginal use cases. - This bug. - Potentially bugs can arise in user code that assumes objects can't contain invalid names.