mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
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.
This commit is contained in:
parent
c94d091889
commit
dba5a798a2
5 changed files with 106 additions and 15 deletions
2
NEWS
2
NEWS
|
@ -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
|
||||
|
|
43
Zend/tests/bug74862.phpt
Normal file
43
Zend/tests/bug74862.phpt
Normal file
|
@ -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) {
|
||||
}
|
46
Zend/tests/bug74862_2.phpt
Normal file
46
Zend/tests/bug74862_2.phpt
Normal file
|
@ -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) {
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue