diff options
-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 |
4 files changed, 104 insertions, 15 deletions
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 1830720336..5f56d0ed9f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4994,8 +4994,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(); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -5005,7 +5005,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(); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 80109fb1ec..77083497c6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3331,8 +3331,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -3342,7 +3342,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -26959,8 +26959,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -26970,7 +26970,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -33915,8 +33915,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -33926,7 +33926,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) : ""); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -48790,8 +48790,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); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -48801,7 +48801,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); ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); |