diff --git a/ext/standard/tests/serialize/serialization_objects_007.phpt b/ext/standard/tests/serialize/unserialize_callback_func/autoload_must_be_called_twice.phpt similarity index 100% rename from ext/standard/tests/serialize/serialization_objects_007.phpt rename to ext/standard/tests/serialize/unserialize_callback_func/autoload_must_be_called_twice.phpt diff --git a/ext/standard/tests/serialize/bug26762.phpt b/ext/standard/tests/serialize/unserialize_callback_func/bug26762.phpt similarity index 100% rename from ext/standard/tests/serialize/bug26762.phpt rename to ext/standard/tests/serialize/unserialize_callback_func/bug26762.phpt diff --git a/ext/standard/tests/serialize/bug70213.phpt b/ext/standard/tests/serialize/unserialize_callback_func/bug70213.phpt similarity index 100% rename from ext/standard/tests/serialize/bug70213.phpt rename to ext/standard/tests/serialize/unserialize_callback_func/bug70213.phpt diff --git a/ext/standard/tests/serialize/unserialize_callback_func/deprecated_partially_supported_callable.phpt b/ext/standard/tests/serialize/unserialize_callback_func/deprecated_partially_supported_callable.phpt new file mode 100644 index 000000000000..a7806581abe5 --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/deprecated_partially_supported_callable.phpt @@ -0,0 +1,51 @@ +--TEST-- +unserialize_callback_func with partially deprecated callable string +--INI-- +unserialize_callback_func=parent::my_unserialize +--FILE-- +getMessage(), PHP_EOL; +} + +try { + $tester = new TesterChild(); + $o = $tester->unserialize($s); + var_dump($o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +echo "Done"; + +?> +--EXPECTF-- +Error: Invalid callback parent::my_unserialize, cannot access "parent" when no class scope is active + +Deprecated: Use of "parent" in callables is deprecated in %s on line %d +callback_called in TesterParent +object(Foo)#3 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn.phpt b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn.phpt new file mode 100644 index 000000000000..67ce94c00dad --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn.phpt @@ -0,0 +1,22 @@ +--TEST-- +unserialize_callback_func with fully qualified name function +--INI-- +unserialize_callback_func=\my_global_fn +--FILE-- + +--EXPECT-- +callback_called +object(Foo)#1 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn_namespace.phpt b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn_namespace.phpt new file mode 100644 index 000000000000..28718bdb2417 --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_fqn_namespace.phpt @@ -0,0 +1,26 @@ +--TEST-- +unserialize_callback_func with fully qualified named namespaced function +--INI-- +unserialize_callback_func=\php\test\my_global_fn +--FILE-- + +--EXPECT-- +callback_called +object(Foo)#1 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/fn_with_null_bytes.phpt b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_null_bytes.phpt new file mode 100644 index 000000000000..5341d4bb6dd8 --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/fn_with_null_bytes.phpt @@ -0,0 +1,25 @@ +--TEST-- +unserialize_callback_func with function name containing null bytes +--FILE-- +getMessage(), PHP_EOL; +} + +echo "Done"; +?> +--EXPECT-- +Error: Invalid callback foo, function "foo" not found or invalid function name +Done diff --git a/ext/standard/tests/serialize/serialization_objects_008.phpt b/ext/standard/tests/serialize/unserialize_callback_func/non_existing.phpt similarity index 100% rename from ext/standard/tests/serialize/serialization_objects_008.phpt rename to ext/standard/tests/serialize/unserialize_callback_func/non_existing.phpt diff --git a/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_private.phpt b/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_private.phpt new file mode 100644 index 000000000000..2b3fb93f3d4a --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_private.phpt @@ -0,0 +1,42 @@ +--TEST-- +unserialize_callback_func with private non-static method +--INI-- +unserialize_callback_func=Tester::my_unserialize +--FILE-- +getMessage(), PHP_EOL; +} + +try { + $tester = new Tester(); + $o = $tester->unserialize($s); + var_dump($o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +echo "Done"; + +?> +--EXPECT-- +Error: Invalid callback Tester::my_unserialize, non-static method Tester::my_unserialize() cannot be called statically +callback_called +object(Foo)#3 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_public.phpt b/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_public.phpt new file mode 100644 index 000000000000..ec09c8285a5e --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/non_static_method_public.phpt @@ -0,0 +1,42 @@ +--TEST-- +unserialize_callback_func with public non-static method +--INI-- +unserialize_callback_func=Tester::my_unserialize +--FILE-- +getMessage(), PHP_EOL; +} + +try { + $tester = new Tester(); + $o = $tester->unserialize($s); + var_dump($o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +echo "Done"; + +?> +--EXPECT-- +Error: Invalid callback Tester::my_unserialize, non-static method Tester::my_unserialize() cannot be called statically +callback_called +object(Foo)#3 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/static_method.phpt b/ext/standard/tests/serialize/unserialize_callback_func/static_method.phpt new file mode 100644 index 000000000000..a96d998cd8c6 --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/static_method.phpt @@ -0,0 +1,26 @@ +--TEST-- +unserialize_callback_func with public static method +--INI-- +unserialize_callback_func=Tester::my_unserialize +--FILE-- + +--EXPECT-- +callback_called +object(Foo)#1 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func/static_method_private.phpt b/ext/standard/tests/serialize/unserialize_callback_func/static_method_private.phpt new file mode 100644 index 000000000000..4bc4e760bed7 --- /dev/null +++ b/ext/standard/tests/serialize/unserialize_callback_func/static_method_private.phpt @@ -0,0 +1,41 @@ +--TEST-- +unserialize_callback_func with private static method +--INI-- +unserialize_callback_func=Tester::my_unserialize +--FILE-- +getMessage(), PHP_EOL; +} + +try { + $o = Tester::unserialize($s); + var_dump($o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +echo "Done"; + +?> +--EXPECT-- +Error: Invalid callback Tester::my_unserialize, cannot access private method Tester::my_unserialize() +callback_called +object(Foo)#2 (0) { +} +Done diff --git a/ext/standard/tests/serialize/unserialize_callback_func_INI_modifications.phpt b/ext/standard/tests/serialize/unserialize_callback_func/unserialize_callback_func_INI_modifications.phpt similarity index 100% rename from ext/standard/tests/serialize/unserialize_callback_func_INI_modifications.phpt rename to ext/standard/tests/serialize/unserialize_callback_func/unserialize_callback_func_INI_modifications.phpt diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 458ad2f12baa..27647c907d3a 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -1256,7 +1256,7 @@ object ":" uiv ":" ["] { } /* Call unserialize callback */ - ZVAL_STR_COPY(&user_func, PG(unserialize_callback_func)); + ZVAL_STR(&user_func, zend_string_dup(PG(unserialize_callback_func), false)); ZVAL_STR(&args[0], class_name); BG(serialize_lock)++;