summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/bug74862.phpt43
-rw-r--r--Zend/tests/bug74862_2.phpt46
-rw-r--r--Zend/zend_vm_def.h6
-rw-r--r--Zend/zend_vm_execute.h24
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();