Internal Serializable object. Hack to create an object without constructor
| From: | Remi Collet | Date: | Thu, 12 Jun 2014 11:48:06 +0000 |
| Subject: | Internal Serializable object. Hack to create an object without constructor | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-74867@lists.php.net to get a copy of this message | ||
Hi,
As Internal Class doesn't support newInstanceWithoutConstructor, some
user code use the above hack (ex phpunit-mock-object)
$object = unserialize(
sprintf('%s:%d:"%s":0:{}',
(version_compare(PHP_VERSION, '5.4', '>')
&& $class->implementsInterface("Serializable") ? "C" :
"O"),
strlen($className),
$className
)
);
Of course, this is already a hack.
Of course, better solution will be to support
newInstanceWithoutConstructor for all internals classes, but this is
another story
Problem, Serializable internal class raised the
'Empty serialized string cannot be empty' exception.
I don't really see any reason to make serialized string mandatory, as
those classes can be create (constructor) without any mandatory option.
The trivial attached patch could make everyone life easier.
The new test serialize again the result object to ensure all internal
structures are properly initialized, and no segfault.
Feedback welcome.
Remi.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
diff -up ext/spl/spl_array.c.orig ext/spl/spl_array.c --- ext/spl/spl_array.c.orig 2014-06-12 13:12:21.693560993 +0200 +++ ext/spl/spl_array.c 2014-06-12 13:13:54.198055264 +0200 @@ -1749,7 +1749,6 @@ SPL_METHOD(Array, unserialize) } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty"); return; } diff -up ext/spl/spl_dllist.c.orig ext/spl/spl_dllist.c --- ext/spl/spl_dllist.c.orig 2014-06-12 13:13:09.590819569 +0200 +++ ext/spl/spl_dllist.c 2014-06-12 13:13:51.513041208 +0200 @@ -1192,7 +1192,6 @@ SPL_METHOD(SplDoublyLinkedList, unserial } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Serialized string cannot be /*empty*/"); return; } diff -up ext/spl/spl_observer.c.orig ext/spl/spl_observer.c --- ext/spl/spl_observer.c.orig 2014-06-12 13:03:36.412701900 +0200 +++ ext/spl/spl_observer.c 2014-06-12 13:03:43.062730695 +0200 @@ -831,7 +831,6 @@ SPL_METHOD(SplObjectStorage, unserialize } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty"); return; } diff -up ext/spl/tests/ArrayObject_unserialize_empty_string.phpt.orig ext/spl/tests/ArrayObject_unserialize_empty_string.phpt --- ext/spl/tests/ArrayObject_unserialize_empty_string.phpt.orig 2014-06-12 13:25:01.406881463 +0200 +++ ext/spl/tests/ArrayObject_unserialize_empty_string.phpt 2014-06-12 13:26:45.098513757 +0200 @@ -1,5 +1,5 @@ --TEST-- -ArrayObject: test that you cannot unserialize a empty string +ArrayObject: test that you can unserialize a empty string --CREDITS-- Havard Eide <nucleuz@gmail.com> #PHPTestFest2009 Norway 2009-06-09 \o/ @@ -8,9 +8,6 @@ Havard Eide <nucleuz@gmail.com> $a = new ArrayObject(array()); $a->unserialize(""); ?> +Done --EXPECTF-- -Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Empty serialized string cannot be empty' in %s.php:%d -Stack trace: -#0 %s(%d): ArrayObject->unserialize('') -#1 {main} - thrown in %s.php on line %d +Done diff -up ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt.orig ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt --- ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt.orig 2014-06-12 13:27:01.011603967 +0200 +++ ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt 2014-06-12 13:29:41.462423018 +0200 @@ -1,5 +1,5 @@ --TEST-- -Check that SplObjectStorage::unserialize throws exception when NULL passed +Check that SplObjectStorage::unserialize desn't throws exception when NULL passed --CREDITS-- PHPNW Testfest 2009 - Simon Westcott (swestcott@gmail.com) --FILE-- @@ -14,6 +14,6 @@ try { } ?> +Done --EXPECTF-- -Empty serialized string cannot be empty - +Done diff -up ext/spl/tests/unserialize.phpt.orig ext/spl/tests/unserialize.phpt --- ext/spl/tests/unserialize.phpt.orig 2014-06-12 13:24:54.342835098 +0200 +++ ext/spl/tests/unserialize.phpt 2014-06-12 13:34:08.743297779 +0200 @@ -0,0 +1,43 @@ +--TEST-- +SPL: unserialize with no data (for PHPUnit) +--FILE-- +<?php + +$types = array('SplDoublyLinkedList', 'SplObjectStorage', 'ArrayObject'); + +foreach ($types as $type) { + // serialize an empty new object + $exp = serialize(new $type()); + // hack to instanciate an object without constructor + $str = sprintf('C:%d:"%s":0:{}', strlen($type), $type); + $obj = unserialize($str); + var_dump($obj); + // serialize result + $out = serialize($obj); + // both should match + var_dump($exp === $out); +} +?> +===DONE=== +--EXPECTF-- +object(SplDoublyLinkedList)#%d (2) { + ["flags":"SplDoublyLinkedList":private]=> + int(0) + ["dllist":"SplDoublyLinkedList":private]=> + array(0) { + } +} +bool(true) +object(SplObjectStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} +bool(true) +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} +bool(true) +===DONE===
diff -up ext/spl/spl_array.c.orig ext/spl/spl_array.c --- ext/spl/spl_array.c.orig 2014-06-12 13:12:21.693560993 +0200 +++ ext/spl/spl_array.c 2014-06-12 13:13:54.198055264 +0200 @@ -1749,7 +1749,6 @@ SPL_METHOD(Array, unserialize) } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty"); return; } diff -up ext/spl/spl_dllist.c.orig ext/spl/spl_dllist.c --- ext/spl/spl_dllist.c.orig 2014-06-12 13:13:09.590819569 +0200 +++ ext/spl/spl_dllist.c 2014-06-12 13:13:51.513041208 +0200 @@ -1192,7 +1192,6 @@ SPL_METHOD(SplDoublyLinkedList, unserial } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Serialized string cannot be /*empty*/"); return; } diff -up ext/spl/spl_observer.c.orig ext/spl/spl_observer.c --- ext/spl/spl_observer.c.orig 2014-06-12 13:03:36.412701900 +0200 +++ ext/spl/spl_observer.c 2014-06-12 13:03:43.062730695 +0200 @@ -831,7 +831,6 @@ SPL_METHOD(SplObjectStorage, unserialize } if (buf_len == 0) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty"); return; } diff -up ext/spl/tests/ArrayObject_unserialize_empty_string.phpt.orig ext/spl/tests/ArrayObject_unserialize_empty_string.phpt --- ext/spl/tests/ArrayObject_unserialize_empty_string.phpt.orig 2014-06-12 13:25:01.406881463 +0200 +++ ext/spl/tests/ArrayObject_unserialize_empty_string.phpt 2014-06-12 13:26:45.098513757 +0200 @@ -1,5 +1,5 @@ --TEST-- -ArrayObject: test that you cannot unserialize a empty string +ArrayObject: test that you can unserialize a empty string --CREDITS-- Havard Eide <nucleuz@gmail.com> #PHPTestFest2009 Norway 2009-06-09 \o/ @@ -8,9 +8,6 @@ Havard Eide <nucleuz@gmail.com> $a = new ArrayObject(array()); $a->unserialize(""); ?> +Done --EXPECTF-- -Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Empty serialized string cannot be empty' in %s.php:%d -Stack trace: -#0 %s(%d): ArrayObject->unserialize('') -#1 {main} - thrown in %s.php on line %d +Done diff -up ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt.orig ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt --- ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt.orig 2014-06-12 13:27:01.011603967 +0200 +++ ext/spl/tests/SplObjectStorage_unserialize_invalid_parameter3.phpt 2014-06-12 13:29:41.462423018 +0200 @@ -1,5 +1,5 @@ --TEST-- -Check that SplObjectStorage::unserialize throws exception when NULL passed +Check that SplObjectStorage::unserialize desn't throws exception when NULL passed --CREDITS-- PHPNW Testfest 2009 - Simon Westcott (swestcott@gmail.com) --FILE-- @@ -14,6 +14,6 @@ try { } ?> +Done --EXPECTF-- -Empty serialized string cannot be empty - +Done diff -up ext/spl/tests/unserialize.phpt.orig ext/spl/tests/unserialize.phpt --- ext/spl/tests/unserialize.phpt.orig 2014-06-12 13:24:54.342835098 +0200 +++ ext/spl/tests/unserialize.phpt 2014-06-12 13:34:08.743297779 +0200 @@ -0,0 +1,43 @@ +--TEST-- +SPL: unserialize with no data (for PHPUnit) +--FILE-- +<?php + +$types = array('SplDoublyLinkedList', 'SplObjectStorage', 'ArrayObject'); + +foreach ($types as $type) { + // serialize an empty new object + $exp = serialize(new $type()); + // hack to instanciate an object without constructor + $str = sprintf('C:%d:"%s":0:{}', strlen($type), $type); + $obj = unserialize($str); + var_dump($obj); + // serialize result + $out = serialize($obj); + // both should match + var_dump($exp === $out); +} +?> +===DONE=== +--EXPECTF-- +object(SplDoublyLinkedList)#%d (2) { + ["flags":"SplDoublyLinkedList":private]=> + int(0) + ["dllist":"SplDoublyLinkedList":private]=> + array(0) { + } +} +bool(true) +object(SplObjectStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} +bool(true) +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} +bool(true) +===DONE===