From 3becd3879f847e8d43fdcedcb7cab8fb46a8ba73 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 21 Feb 2012 10:34:42 +0000 Subject: [PATCH] Add a __wakeup() method to SplFixedArray, thereby fixing serialising an SplFixedArray object and bug #60560 (SplFixedArray un-/serialize, getSize(), count() return 0, keys are strings). --- NEWS | 2 + ext/spl/spl_fixedarray.c | 33 ++++++++++++++ ext/spl/tests/SplFixedArray_serialize.phpt | 52 ++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 ext/spl/tests/SplFixedArray_serialize.phpt diff --git a/NEWS b/NEWS index 8a209b5efff..6c04f81c880 100644 --- a/NEWS +++ b/NEWS @@ -49,6 +49,8 @@ PHP NEWS . Fixed bug #65136 (RecursiveDirectoryIterator segfault). (Laruence) . Fixed bug #61828 (Memleak when calling Directory(Recursive)Iterator /Spl(Temp)FileObject ctor twice). (Laruence) + . Fixed bug #60560 (SplFixedArray un-/serialize, getSize(), count() return 0, + keys are strings). (Adam) ?? ??? 2013, PHP 5.4.17 diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index ebc4e341a67..fec7e2c4aca 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -604,6 +604,38 @@ SPL_METHOD(SplFixedArray, __construct) } /* }}} */ +/* {{{ proto void SplFixedArray::__wakeup() +*/ +SPL_METHOD(SplFixedArray, __wakeup) +{ + spl_fixedarray_object *intern = (spl_fixedarray_object *) zend_object_store_get_object(getThis() TSRMLS_CC); + HashPosition ptr; + HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC); + zval **data; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { + return; + } + + if (!intern->array) { + int index = 0; + int size = zend_hash_num_elements(intern_ht); + + intern->array = emalloc(sizeof(spl_fixedarray)); + spl_fixedarray_init(intern->array, size TSRMLS_CC); + + for (zend_hash_internal_pointer_reset_ex(intern_ht, &ptr); zend_hash_get_current_data_ex(intern_ht, (void **) &data, &ptr) == SUCCESS; zend_hash_move_forward_ex(intern_ht, &ptr)) { + Z_ADDREF_PP(data); + intern->array->elements[index++] = *data; + } + + /* Remove the unserialised properties, since we now have the elements + * within the spl_fixedarray_object structure. */ + zend_hash_clean(intern_ht); + } +} +/* }}} */ + /* {{{ proto int SplFixedArray::count(void) */ SPL_METHOD(SplFixedArray, count) @@ -1086,6 +1118,7 @@ ZEND_END_ARG_INFO() static zend_function_entry spl_funcs_SplFixedArray[] = { /* {{{ */ SPL_ME(SplFixedArray, __construct, arginfo_splfixedarray_construct,ZEND_ACC_PUBLIC) + SPL_ME(SplFixedArray, __wakeup, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC) SPL_ME(SplFixedArray, count, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC) SPL_ME(SplFixedArray, toArray, arginfo_splfixedarray_void, ZEND_ACC_PUBLIC) SPL_ME(SplFixedArray, fromArray, arginfo_fixedarray_fromArray, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) diff --git a/ext/spl/tests/SplFixedArray_serialize.phpt b/ext/spl/tests/SplFixedArray_serialize.phpt new file mode 100644 index 00000000000..f99812ecceb --- /dev/null +++ b/ext/spl/tests/SplFixedArray_serialize.phpt @@ -0,0 +1,52 @@ +--TEST-- +SplFixedArray serialisation +--FILE-- +prop = 'value'; + +$array[0] = 'foo'; +$array[2] = 42; +$array[3] = $obj; +$array[4] = range(1, 5); + +$ser = serialize($array); +echo "$ser\n"; +$unser = unserialize($ser); + +printf("count: %d\n", count($unser)); +printf("getSize(): %d\n", $unser->getSize()); + +var_dump($unser[0], $unser[1], $unser[2], $unser[3], $unser[4]); + +$unser[4] = 'quux'; +var_dump($unser[4]); + +?> +--EXPECT-- +O:13:"SplFixedArray":5:{i:0;s:3:"foo";i:1;N;i:2;i:42;i:3;O:8:"stdClass":1:{s:4:"prop";s:5:"value";}i:4;a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}} +count: 5 +getSize(): 5 +string(3) "foo" +NULL +int(42) +object(stdClass)#4 (1) { + ["prop"]=> + string(5) "value" +} +array(5) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + [3]=> + int(4) + [4]=> + int(5) +} +string(4) "quux"