I've attached a patch (both for HEAD and the PHP_5_3 branch) that allows the
magic __sleep() method to return NULL to continue the normal serialization
process (all members are serialized). This allows the __sleep() method to do
meaningful cleanup without having to resort to Reflection overhead. The patch
retains the original behavior (E_NOTICE) if anything other than an array or
NULL is returned from the function.
I check the results of a "make test" on the PHP_5_3 branch with and without the
patch. I skipped the results from HEAD because there were so many unrelated
failures it was pointless. The one additional failure in 5.3 with the patch is
actually a reverse unit test. I've included a patch (separately, because it's
the same for HEAD and PHP_5_3) to correct the expected result from this test.
Thanks,
Andrew
Index: ext/standard/var.c
===================================================================
RCS file: /repository/php-src/ext/standard/var.c,v
retrieving revision 1.203.2.7.2.18.2.4
diff -u -r1.203.2.7.2.18.2.4 var.c
--- ext/standard/var.c 2 Nov 2007 19:40:39 -0000 1.203.2.7.2.18.2.4
+++ ext/standard/var.c 6 Nov 2007 19:44:51 -0000
@@ -726,19 +726,21 @@
ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0);
res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
- if (res == SUCCESS && !EG(exception)) {
- if (retval_ptr) {
- if (HASH_OF(retval_ptr)) {
- php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
- /* we should still add element even if it's not OK,
- * since we already wrote the length of the array before */
- smart_str_appendl(buf,"N;", 2);
- }
+ if (res == SUCCESS && !EG(exception) && retval_ptr) {
+ /* only serialize using the return value
+ if it's an array, allow NULLs to fall through */
+ if (HASH_OF(retval_ptr)) {
+ php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
zval_ptr_dtor(&retval_ptr);
+ return;
+ } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
+ /* we should still add element even if it's not OK,
+ since we already wrote the length of the array before */
+ smart_str_appendl(buf,"N;", 2);
+ zval_ptr_dtor(&retval_ptr);
+ return;
}
- return;
}
}
Index: ext/standard/var.c
===================================================================
RCS file: /repository/php-src/ext/standard/var.c,v
retrieving revision 1.271
diff -u -r1.271 var.c
--- ext/standard/var.c 2 Nov 2007 09:43:04 -0000 1.271
+++ ext/standard/var.c 6 Nov 2007 19:22:24 -0000
@@ -1003,19 +1003,24 @@
ZVAL_ASCII_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 1);
res = call_user_function_ex(CG(function_table), &struc, &fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
zval_dtor(&fname);
- if (res == SUCCESS && !EG(exception)) {
- if (retval_ptr) {
- if (HASH_OF(retval_ptr)) {
- php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
- } else {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize");
- /* we should still add element even if it's not OK,
- * since we already wrote the length of the array before */
- smart_str_appendl(buf,"N;", 2);
- }
+
+ if (res == SUCCESS && !EG(exception) && retval_ptr) {
+ /* only serialize using the return value
+ if it's an array, allow NULLs to fall through */
+ if (HASH_OF(retval_ptr)) {
+ php_var_serialize_class(buf, struc, retval_ptr, var_hash TSRMLS_CC);
+ zval_ptr_dtor(&retval_ptr);
+ return;
+ } else if (Z_TYPE_P(retval_ptr) != IS_NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "__sleep should return an array "
+ "containing the names of instance-variables to "
+ "serialize, or NULL.");
+ /* we should still add element even if it's not OK,
+ since we already wrote the length of the array before */
+ smart_str_appendl(buf,"N;", 2);
zval_ptr_dtor(&retval_ptr);
+ return;
}
- return;
}
}
Index: ext/standard/tests/serialize/bug21957.phpt
===================================================================
RCS file: /repository/php-src/ext/standard/tests/serialize/bug21957.phpt,v
retrieving revision 1.2
diff -u -r1.2 bug21957.phpt
--- ext/standard/tests/serialize/bug21957.phpt 30 Nov 2003 13:57:18 -0000 1.2
+++ ext/standard/tests/serialize/bug21957.phpt 6 Nov 2007 20:44:36 -0000
@@ -40,10 +40,15 @@
int(2)
}
}
-a:2:{s:3:"one";s:3:"ABC";s:3:"two";N;}
+a:2:{s:3:"one";s:3:"ABC";s:3:"two";O:4:"test":2:{s:1:"a";i:7;s:1:"b";i:0;}}
array(2) {
["one"]=>
string(3) "ABC"
["two"]=>
- NULL
+ object(test)#2 (2) {
+ ["a"]=>
+ int(7)
+ ["b"]=>
+ int(0)
+ }
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php