diff options
author | DanielCiochiu <daniel@ciochiu.ro> | 2017-11-07 07:30:34 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2017-11-15 23:00:26 +0100 |
commit | dba5a798a28482ce4a6475cc4de1586f11126175 (patch) | |
tree | 041948a5096661a2b9bec0906f0c361e9cf8b9f2 | |
parent | c94d091889a67472f6da7d56db681ec8cf5be0f3 (diff) | |
download | php-git-dba5a798a28482ce4a6475cc4de1586f11126175.tar.gz |
Fixed #74862: Unable to clone instance when private __clone defined
Even though __clone was implemented as private and called only from
parent class, child extending class instance could not be cloned.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug74862.phpt | 43 | ||||
-rw-r--r-- | Zend/tests/bug74862_2.phpt | 46 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 6 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 24 |
5 files changed, 106 insertions, 15 deletions
@@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug #75384 (PHP seems incompatible with OneDrive files on demand). (Anatol) + . Fixed bug #74862 (Unable to clone instance when private __clone defined). + (Daniel Ciochiu) - CLI Server: . Fixed bug #60471 (Random "Invalid request (unexpected EOF)" using a router diff --git a/Zend/tests/bug74862.phpt b/Zend/tests/bug74862.phpt new file mode 100644 index 0000000000..7822575d04 --- /dev/null +++ b/Zend/tests/bug74862.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #74862 (Unable to clone instance when private __clone defined) +--FILE-- +<?php + +class a { + private function __clone() + { + + } + + private function __construct() + { + + } + + public static function getInstance() + { + return new static(); + } + + public function cloneIt() + { + $a = clone $this; + + return $a; + } +} + +class c extends a { + +} + +// private constructor +$d = c::getInstance(); + +// private clone +$e = $d->cloneIt(); +var_dump($e); +?> +--EXPECT-- +object(c)#2 (0) { +} diff --git a/Zend/tests/bug74862_2.phpt b/Zend/tests/bug74862_2.phpt new file mode 100644 index 0000000000..2e544a380e --- /dev/null +++ b/Zend/tests/bug74862_2.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #74862 (Unable to clone instance when private __clone defined in a child class) +--FILE-- +<?php + +class main { +} + +class a extends main { + private function __clone() + { + + } + + private function __construct() + { + + } + + public static function getInstance() + { + return new static(); + } + + public function cloneIt() + { + $a = clone $this; + + return $a; + } +} + +class c extends a { + +} + +// private constructor +$d = c::getInstance(); + +// private clone +$e = $d->cloneIt(); +var_dump($e); +?> +--EXPECT-- +object(c)#2 (0) { +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9a633780b1..08eb762a99 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5080,8 +5080,8 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) /* Ensure that if we're calling a private function, we're allowed to do so. */ scope = EX(func)->op_array.scope; - if (UNEXPECTED(ce != scope)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + if (!zend_check_private(clone, scope, clone->common.function_name)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); FREE_OP1(); HANDLE_EXCEPTION(); } @@ -5090,7 +5090,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) */ scope = EX(func)->op_array.scope; if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); FREE_OP1(); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bb4f50a431..94949e8881 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3307,8 +3307,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_ /* Ensure that if we're calling a private function, we're allowed to do so. */ scope = EX(func)->op_array.scope; - if (UNEXPECTED(ce != scope)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + if (!zend_check_private(clone, scope, clone->common.function_name)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -3317,7 +3317,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_ */ scope = EX(func)->op_array.scope; if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -28031,8 +28031,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND /* Ensure that if we're calling a private function, we're allowed to do so. */ scope = EX(func)->op_array.scope; - if (UNEXPECTED(ce != scope)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + if (!zend_check_private(clone, scope, clone->common.function_name)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -28041,7 +28041,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND */ scope = EX(func)->op_array.scope; if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -35361,8 +35361,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC /* Ensure that if we're calling a private function, we're allowed to do so. */ scope = EX(func)->op_array.scope; - if (UNEXPECTED(ce != scope)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + if (!zend_check_private(clone, scope, clone->common.function_name)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -35371,7 +35371,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC */ scope = EX(func)->op_array.scope; if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -51620,8 +51620,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND /* Ensure that if we're calling a private function, we're allowed to do so. */ scope = EX(func)->op_array.scope; - if (UNEXPECTED(ce != scope)) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + if (!zend_check_private(clone, scope, clone->common.function_name)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } @@ -51630,7 +51630,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND */ scope = EX(func)->op_array.scope; if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : ""); zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } |