Skip to content

Commit 78b7ac4

Browse files
committed
zend_vm: Support property list in ZEND_CLONE
1 parent 9420cc9 commit 78b7ac4

File tree

2 files changed

+135
-20
lines changed

2 files changed

+135
-20
lines changed

Zend/zend_vm_def.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6005,9 +6005,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60056005
SAVE_OPLINE();
60066006
obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
60076007

6008-
/* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync.
6009-
* The OPcode intentionally does not support a clone-with property list to keep it simple.
6010-
*/
6008+
/* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */
60116009

60126010
do {
60136011
if (OP1_TYPE == IS_CONST ||
@@ -6027,6 +6025,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60276025
}
60286026
zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj));
60296027
FREE_OP1();
6028+
FREE_OP2();
60306029
HANDLE_EXCEPTION();
60316030
}
60326031
} while (0);
@@ -6037,6 +6036,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60376036
if (UNEXPECTED(zobj->handlers->clone_obj == NULL)) {
60386037
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
60396038
FREE_OP1();
6039+
FREE_OP2();
60406040
ZVAL_UNDEF(EX_VAR(opline->result.var));
60416041
HANDLE_EXCEPTION();
60426042
}
@@ -6048,6 +6048,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60486048
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
60496049
zend_bad_method_call(clone, clone->common.function_name, scope);
60506050
FREE_OP1();
6051+
FREE_OP2();
60516052
ZVAL_UNDEF(EX_VAR(opline->result.var));
60526053
HANDLE_EXCEPTION();
60536054
}
@@ -6057,8 +6058,29 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60576058
zend_object *cloned;
60586059
if (zobj->handlers->clone_obj_with) {
60596060
scope = EX(func)->op_array.scope;
6060-
cloned = zobj->handlers->clone_obj_with(zobj, scope, &zend_empty_array);
6061+
if (OP2_TYPE != IS_UNUSED) {
6062+
zval *properties = GET_OP2_ZVAL_PTR(BP_VAR_R);
6063+
if (Z_TYPE_P(properties) != IS_ARRAY) {
6064+
zend_type_error("clone(): Argument #2 ($withProperties) must be of type array, %s given", zend_zval_value_name(obj));
6065+
FREE_OP1();
6066+
FREE_OP2();
6067+
ZVAL_UNDEF(EX_VAR(opline->result.var));
6068+
HANDLE_EXCEPTION();
6069+
}
6070+
6071+
cloned = zobj->handlers->clone_obj_with(zobj, scope, Z_ARR_P(properties));
6072+
} else {
6073+
cloned = zobj->handlers->clone_obj_with(zobj, scope, &zend_empty_array);
6074+
}
60616075
} else {
6076+
if (OP2_TYPE != IS_UNUSED) {
6077+
zend_throw_error(NULL, "Trying to clone an object with updated properties that is not compatible %s", ZSTR_VAL(ce->name));
6078+
FREE_OP1();
6079+
FREE_OP2();
6080+
ZVAL_UNDEF(EX_VAR(opline->result.var));
6081+
HANDLE_EXCEPTION();
6082+
}
6083+
60626084
cloned = zobj->handlers->clone_obj(zobj);
60636085
}
60646086

@@ -6069,6 +6091,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
60696091
ZVAL_UNDEF(EX_VAR(opline->result.var));
60706092
}
60716093
FREE_OP1();
6094+
FREE_OP2();
60726095
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
60736096
}
60746097

Zend/zend_vm_execute.h

Lines changed: 108 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)