diff --git a/NEWS b/NEWS index f32c78a4f8f..a747b528384 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug #75384 (PHP seems incompatible with OneDrive files on demand). (Anatol) . Fixed bug #75525 (Access Violation in vcruntime140.dll). (Anatol) + . Fixed bug #74862 (Unable to clone instance when private __clone defined). + (Daniel Ciochiu) - Standard: . Fixed bug #75511 (fread not free unused buffer). (Laruence) diff --git a/Zend/tests/bug74862.phpt b/Zend/tests/bug74862.phpt new file mode 100644 index 00000000000..7822575d04f --- /dev/null +++ b/Zend/tests/bug74862.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #74862 (Unable to clone instance when private __clone defined) +--FILE-- +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 00000000000..2e544a380ec --- /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-- +cloneIt(); +var_dump($e); +?> +--EXPECT-- +object(c)#2 (0) { +} diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1c3668088ef..dc52e00bc27 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4957,8 +4957,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(); @@ -4968,7 +4968,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 6b83684b7f3..d1ea87bf682 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3324,8 +3324,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(); @@ -3335,7 +3335,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(); @@ -26863,8 +26863,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(); @@ -26874,7 +26874,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(); @@ -33751,8 +33751,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(); @@ -33762,7 +33762,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(); @@ -48594,8 +48594,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(); @@ -48605,7 +48605,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();