From bc391e7f25bc69d888dbb335f35a2a5f8cce10aa Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Fri, 18 Jun 2021 07:12:30 +0200 Subject: [PATCH 1/2] Fix bug #81163 __sleep allowed to return non-array --- ext/standard/tests/serialize/bug81163.phpt | 21 +++++++++++++++++++++ ext/standard/var.c | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/serialize/bug81163.phpt diff --git a/ext/standard/tests/serialize/bug81163.phpt b/ext/standard/tests/serialize/bug81163.phpt new file mode 100644 index 0000000000000..855fc1c953ed2 --- /dev/null +++ b/ext/standard/tests/serialize/bug81163.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test __sleep returns non-array +--FILE-- + +--EXPECTF-- +Warning: serialize(): bar::__sleep() should return an array only containing the names of instance-variables to serialize in %s on line %d diff --git a/ext/standard/var.c b/ext/standard/var.c index ee4657338102a..68cf5e7c83592 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -791,7 +791,7 @@ static zend_result php_var_serialize_call_sleep(zend_object *obj, zend_function return FAILURE; } - if (!HASH_OF(retval)) { + if (Z_TYPE_P(retval) != IS_ARRAY) { zval_ptr_dtor(retval); php_error_docref(NULL, E_WARNING, "%s::__sleep() should return an array only containing the names of instance-variables to serialize", ZSTR_VAL(obj->ce->name)); return FAILURE; @@ -980,7 +980,8 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, php_serialize_data_t var_hash) /* {{{ */ { HashTable props; - if (php_var_serialize_get_sleep_props(&props, struc, HASH_OF(retval_ptr)) == SUCCESS) { + + if (php_var_serialize_get_sleep_props(&props, struc, Z_ARRVAL_P(retval_ptr)) == SUCCESS) { php_var_serialize_class_name(buf, struc); php_var_serialize_nested_data( buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ 0, var_hash); From 696d9d656f56a4718cd83fdaf45092d34d8a967d Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Fri, 18 Jun 2021 10:54:06 +0200 Subject: [PATCH 2/2] more --- ext/standard/var.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ext/standard/var.c b/ext/standard/var.c index 68cf5e7c83592..1923c2ede24be 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -764,15 +764,16 @@ static inline bool php_var_serialize_class_name(smart_str *buf, zval *struc) /* } /* }}} */ -static zend_result php_var_serialize_call_sleep(zend_object *obj, zend_function *fn, zval *retval) /* {{{ */ +static HashTable* php_var_serialize_call_sleep(zend_object *obj, zend_function *fn) /* {{{ */ { zend_result res; zend_fcall_info fci; zend_fcall_info_cache fci_cache; + zval retval; fci.size = sizeof(fci); fci.object = obj; - fci.retval = retval; + fci.retval = &retval; fci.param_count = 0; fci.params = NULL; fci.named_params = NULL; @@ -786,18 +787,18 @@ static zend_result php_var_serialize_call_sleep(zend_object *obj, zend_function res = zend_call_function(&fci, &fci_cache); BG(serialize_lock)--; - if (res == FAILURE || Z_ISUNDEF_P(retval)) { - zval_ptr_dtor(retval); - return FAILURE; + if (res == FAILURE || Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); + return NULL; } - if (Z_TYPE_P(retval) != IS_ARRAY) { - zval_ptr_dtor(retval); + if (Z_TYPE(retval) != IS_ARRAY) { + zval_ptr_dtor(&retval); php_error_docref(NULL, E_WARNING, "%s::__sleep() should return an array only containing the names of instance-variables to serialize", ZSTR_VAL(obj->ce->name)); - return FAILURE; + return NULL; } - return SUCCESS; + return Z_ARRVAL(retval); } /* }}} */ @@ -977,11 +978,11 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable } /* }}} */ -static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, php_serialize_data_t var_hash) /* {{{ */ +static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht, php_serialize_data_t var_hash) /* {{{ */ { HashTable props; - if (php_var_serialize_get_sleep_props(&props, struc, Z_ARRVAL_P(retval_ptr)) == SUCCESS) { + if (php_var_serialize_get_sleep_props(&props, struc, ht) == SUCCESS) { php_var_serialize_class_name(buf, struc); php_var_serialize_nested_data( buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ 0, var_hash); @@ -1159,10 +1160,11 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ zval *zv = zend_hash_find_ex(&ce->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP), 1); if (zv) { - zval retval, tmp; + HashTable *ht; + zval tmp; ZVAL_OBJ_COPY(&tmp, Z_OBJ_P(struc)); - if (php_var_serialize_call_sleep(Z_OBJ(tmp), Z_FUNC_P(zv), &retval) == FAILURE) { + if (!(ht = php_var_serialize_call_sleep(Z_OBJ(tmp), Z_FUNC_P(zv)))) { if (!EG(exception)) { /* we should still add element even if it's not OK, * since we already wrote the length of the array before */ @@ -1172,8 +1174,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_ return; } - php_var_serialize_class(buf, &tmp, &retval, var_hash); - zval_ptr_dtor(&retval); + php_var_serialize_class(buf, &tmp, ht, var_hash); + zend_array_release(ht); OBJ_RELEASE(Z_OBJ(tmp)); return; }