summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielCiochiu <daniel@ciochiu.ro>2017-11-07 07:30:34 +0200
committerNikita Popov <nikita.ppv@gmail.com>2017-11-15 23:00:26 +0100
commitdba5a798a28482ce4a6475cc4de1586f11126175 (patch)
tree041948a5096661a2b9bec0906f0c361e9cf8b9f2
parentc94d091889a67472f6da7d56db681ec8cf5be0f3 (diff)
downloadphp-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--NEWS2
-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
5 files changed, 106 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index 2161afaa52..d5b94bd809 100644
--- a/NEWS
+++ b/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
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();
}