diff options
-rw-r--r-- | Zend/tests/bug30332.phpt | 40 | ||||
-rw-r--r-- | Zend/tests/bug31828.phpt | 25 | ||||
-rw-r--r-- | Zend/tests/bug32080.phpt | 18 | ||||
-rw-r--r-- | Zend/tests/bug32852.phpt | 38 | ||||
-rwxr-xr-x | Zend/tests/bug33243.phpt | 25 | ||||
-rwxr-xr-x | Zend/tests/bug34712.phpt | 28 | ||||
-rwxr-xr-x | Zend/tests/bug34767.phpt | 33 | ||||
-rw-r--r-- | Zend/zend.c | 1 | ||||
-rw-r--r-- | Zend/zend_API.c | 19 | ||||
-rw-r--r-- | Zend/zend_execute.c | 104 | ||||
-rw-r--r-- | Zend/zend_execute.h | 9 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 7 | ||||
-rw-r--r-- | Zend/zend_globals.h | 1 | ||||
-rw-r--r-- | Zend/zend_objects.c | 7 | ||||
-rw-r--r-- | Zend/zend_operators.c | 36 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 20 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 80 |
17 files changed, 474 insertions, 17 deletions
diff --git a/Zend/tests/bug30332.phpt b/Zend/tests/bug30332.phpt new file mode 100644 index 0000000000..e2478498cd --- /dev/null +++ b/Zend/tests/bug30332.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #30332 (zend.ze1_compatibility_mode isnt fully compatable with array_push()) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +<?php +class x { }; + +$first = new x; +$second = $first; +$container = array(); +array_push($container, $first); + +$first->first = " im in the first"; + +print_r($first); +print_r($second); +print_r($container); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 4 + +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 5 + +Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 7 +x Object +( + [first] => im in the first +) +x Object +( +) +Array +( + [0] => x Object + ( + ) + +) diff --git a/Zend/tests/bug31828.phpt b/Zend/tests/bug31828.phpt new file mode 100644 index 0000000000..a3cc4542fd --- /dev/null +++ b/Zend/tests/bug31828.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #31828 (Crash with zend.ze1_compatibility_mode=On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +<?php +$o = new stdClass(); +$o->id = 77; +$o->name = "Aerospace"; +$a[] = $o; +$a = $a[0]; +print_r($a); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 2 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 5 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 6 +stdClass Object +( + [id] => 77 + [name] => Aerospace +) diff --git a/Zend/tests/bug32080.phpt b/Zend/tests/bug32080.phpt new file mode 100644 index 0000000000..a96c8bf262 --- /dev/null +++ b/Zend/tests/bug32080.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #32080 (segfault when assigning object to itself with zend.ze1_compatibility_mode=On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +<?php +class test { } +$t = new test; +$t = $t; // gives segfault +var_dump($t); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 3 + +Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 5 +object(test)#%d (0) { +} diff --git a/Zend/tests/bug32852.phpt b/Zend/tests/bug32852.phpt new file mode 100644 index 0000000000..38cea6f145 --- /dev/null +++ b/Zend/tests/bug32852.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #32852 (Crash with singleton and __destruct when zend.ze1_compatibility_mode = On) +--INI-- +zend.ze1_compatibility_mode=on +error_reporting=4095 +--FILE-- +<?php +class crashme { + private static $instance = null; + + public function __construct() { + self::$instance = $this; + } + + public function __destruct() { + echo "i'm called\n"; + } + + public static function singleton() { + if (!isset(self::$instance)) { + self::$instance = new crashme(); + } + return self::$instance; + } +} + +crashme::singleton(); +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 6 +i'm called + +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 15 +i'm called + +Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 17 +i'm called +i'm called diff --git a/Zend/tests/bug33243.phpt b/Zend/tests/bug33243.phpt new file mode 100755 index 0000000000..bb5d77c7bf --- /dev/null +++ b/Zend/tests/bug33243.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #33243 (ze1_compatibility_mode does not work as expected) +--INI-- +zend.ze1_compatibility_mode=1 +error_reporting=4095 +--FILE-- +<?php +$a->y->z = 0; +$b = $a; // should perform deep copy of $a +$b->y->z = 1; // hence this should have no effect on $a +var_dump($a); +?> +--EXPECTF-- +Strict Standards: Creating default object from empty value in %sbug33243.php on line 2 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 3 + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 5 +object(stdClass)#%d (1) { + ["y"]=> + object(stdClass)#%d (1) { + ["z"]=> + int(0) + } +} diff --git a/Zend/tests/bug34712.phpt b/Zend/tests/bug34712.phpt new file mode 100755 index 0000000000..db7860cd38 --- /dev/null +++ b/Zend/tests/bug34712.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #34712 zend.ze1_compatibility_mode = on segfault +--INI-- +zend.ze1_compatibility_mode=1 +error_reporting=4095 +--FILE-- +<?php +class foo { + function foo(&$obj_ref) { + $this->bar = &$obj_ref; + } +} + + +class bar { + function bar() { + $this->foo = new foo($this); + } +} + +$test = new bar; +echo "ok\n"; +?> +--EXPECTF-- +Strict Standards: Implicit cloning object of class 'foo' because of 'zend.ze1_compatibility_mode' in %sbug34712.php on line 11 + +Strict Standards: Implicit cloning object of class 'bar' because of 'zend.ze1_compatibility_mode' in %sbug34712.php on line 15 +ok diff --git a/Zend/tests/bug34767.phpt b/Zend/tests/bug34767.phpt new file mode 100755 index 0000000000..45af9f944c --- /dev/null +++ b/Zend/tests/bug34767.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #34767 (Zend Engine 1 Compatibility not copying objects correctly) +--INI-- +zend.ze1_compatibility_mode=1 +error_reporting=4095 +--FILE-- +<?php +$a->y = &new stdClass(); +print_r($a); +$b = $a; +$a->y->z = 1; +print_r($b); +?> +--EXPECTF-- + +Strict Standards: Assigning the return value of new by reference is deprecated in %sbug34767.php on line 2 +stdClass Object +( + [y] => stdClass Object + ( + ) + +) + +Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug34767.php on line 4 +stdClass Object +( + [y] => stdClass Object + ( + [z] => 1 + ) + +) diff --git a/Zend/zend.c b/Zend/zend.c index d63ec97198..e12598e63d 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -77,6 +77,7 @@ static ZEND_INI_MH(OnUpdateErrorReporting) ZEND_INI_BEGIN() ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) + STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals) #ifdef ZEND_MULTIBYTE STD_ZEND_INI_BOOLEAN("detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals) #endif diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b87da8884e..b32b9eb47d 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -154,6 +154,25 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr while (param_count-->0) { zval **value = (zval**)(p-arg_count); + if (EG(ze1_compatibility_mode) && Z_TYPE_PP(value) == IS_OBJECT) { + zval *value_ptr; + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC); + + ALLOC_ZVAL(value_ptr); + *value_ptr = **value; + INIT_PZVAL(value_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + if(!dup) { + efree(class_name); + } + value_ptr->value.obj = Z_OBJ_HANDLER_PP(value, clone_obj)(*value TSRMLS_CC); + zval_ptr_dtor(value); + *value = value_ptr; + } *(argument_array++) = value; arg_count--; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f7a19a5845..99fb7ac7ad 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -554,11 +554,30 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode FREE_OP(free_value); return; } - + /* here we are sure we are dealing with an object */ /* separate our value if necessary */ - if (value_op->op_type == IS_TMP_VAR) { + if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { + zval *orig_value = value; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(value); + *value = *orig_value; + value->is_ref = 0; + value->refcount = 0; + dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC); + if(!dup) { + efree(class_name); + } + } else if (value_op->op_type == IS_TMP_VAR) { zval *orig_value = value; ALLOC_ZVAL(value); @@ -701,7 +720,55 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2 goto done_setting_var; } - if (PZVAL_IS_REF(variable_ptr)) { + if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC); + + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } else if (PZVAL_IS_REF(variable_ptr)) { + if (variable_ptr != value) { + zend_uint refcount = variable_ptr->refcount; + zval garbage; + + if (type != IS_TMP_VAR) { + value->refcount++; + } + garbage = *variable_ptr; + *variable_ptr = *value; + variable_ptr->refcount = refcount; + variable_ptr->is_ref = 1; + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + if (type != IS_TMP_VAR) { + value->refcount--; + } + zendi_zval_dtor(garbage); + } + } else { + if (variable_ptr != value) { + value->refcount++; + variable_ptr->refcount--; + if (variable_ptr->refcount == 0) { + zendi_zval_dtor(*variable_ptr); + } else { + ALLOC_ZVAL(variable_ptr); + *variable_ptr_ptr = variable_ptr; + } + *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + zval_ptr_dtor(&value); + } + } + if (!dup) { + efree(class_name); + } + } else if (PZVAL_IS_REF(variable_ptr)) { if (variable_ptr!=value) { zend_uint refcount = variable_ptr->refcount; zval garbage; @@ -791,9 +858,34 @@ done_setting_var: static inline void zend_receive(zval **variable_ptr_ptr, zval *value TSRMLS_DC) { - (*variable_ptr_ptr)->refcount--; - *variable_ptr_ptr = value; - value->refcount++; + zval *variable_ptr = *variable_ptr_ptr; + + if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) { + char *class_name; + zend_uint class_name_len; + int dup; + + dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC); + + if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } else { + variable_ptr->refcount--; + ALLOC_ZVAL(variable_ptr); + *variable_ptr_ptr = variable_ptr; + *variable_ptr = *value; + INIT_PZVAL(variable_ptr); + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC); + } + if (!dup) { + efree(class_name); + } + } else { + variable_ptr->refcount--; + *variable_ptr_ptr = value; + value->refcount++; + } } /* Utility Functions for Extensions */ diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index a76c688513..11b92bd680 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -116,8 +116,15 @@ static inline int i_zend_is_true(zval *op) break; } } + + if(EG(ze1_compatibility_mode)) { + result = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0); + } else { + result = 1; + } + } else { + result = 1; } - result = 1; break; default: result = 0; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 7b9f141775..e7d78c4029 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -395,6 +395,13 @@ ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) zval_dtor(*zval_ptr); safe_free_zval_ptr_rel(*zval_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC); } else if ((*zval_ptr)->refcount == 1) { + if ((*zval_ptr)->type == IS_OBJECT) { + TSRMLS_FETCH(); + + if (EG(ze1_compatibility_mode)) { + return; + } + } (*zval_ptr)->is_ref = 0; } } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index d1bda5b064..72d045e281 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -200,6 +200,7 @@ struct _zend_executor_globals { HashTable *in_autoload; zend_function *autoload_func; zend_bool full_tables_cleanup; + zend_bool ze1_compatibility_mode; /* for extended information support */ zend_bool no_extensions; diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index e2d86e8fe8..6dc4ba4aa3 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -158,8 +158,11 @@ static void zval_add_ref_or_clone(zval **p) ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC) { - zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); - + if (EG(ze1_compatibility_mode)) { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref_or_clone, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } else { + zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *)); + } if (old_object->ce->clone) { zval *new_obj; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 65a224840a..37f412fe75 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -340,7 +340,14 @@ ZEND_API void convert_to_long_base(zval *op, int base) return; } - zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name); + if (EG(ze1_compatibility_mode)) { + HashTable *ht = Z_OBJPROP_P(op); + if (ht) { + retval = (zend_hash_num_elements(ht)?1:0); + } + } else { + zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name); + } zval_dtor(op); ZVAL_LONG(op, retval); return; @@ -399,7 +406,15 @@ ZEND_API void convert_to_double(zval *op) return; } - zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name); + if (EG(ze1_compatibility_mode)) { + HashTable *ht = Z_OBJPROP_P(op); + if (ht) { + retval = (zend_hash_num_elements(ht)?1.0:0.0); + } + } else { + zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name); + } + zval_dtor(op); ZVAL_DOUBLE(op, retval); break; @@ -486,6 +501,13 @@ ZEND_API void convert_to_boolean(zval *op) return; } + if (EG(ze1_compatibility_mode)) { + HashTable *ht = Z_OBJPROP_P(op); + if (ht) { + retval = (zend_hash_num_elements(ht)?1:0); + } + } + zval_dtor(op); ZVAL_BOOL(op, retval); break; @@ -1452,7 +1474,15 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) break; case IS_OBJECT: if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) { - result->value.lval = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)); + if (EG(ze1_compatibility_mode)) { + zend_compare_objects(result, op1, op2 TSRMLS_CC); + /* comparison returns 0 in case of equality and + * 1 in case of ineqaulity, we need to reverse it + */ + result->value.lval = !result->value.lval; + } else { + result->value.lval = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)); + } } else { result->value.lval = 0; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b69a7a6017..5295320de9 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2047,7 +2047,25 @@ ZEND_VM_C_LABEL(return_by_value): retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); - if (!IS_OP1_TMP_FREE()) { /* Not a temp var */ + if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + zval *ret; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, retval_ptr); + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + *EG(return_value_ptr_ptr) = ret; + if (!dup) { + efree(class_name); + } + } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { zval *ret; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0300a92c45..8dc247d4fd 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1686,7 +1686,25 @@ return_by_value: retval_ptr = &opline->op1.u.constant; - if (!0) { /* Not a temp var */ + if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + zval *ret; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, retval_ptr); + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + *EG(return_value_ptr_ptr) = ret; + if (!dup) { + efree(class_name); + } + } else if (!0) { /* Not a temp var */ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { zval *ret; @@ -4115,7 +4133,25 @@ return_by_value: retval_ptr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!1) { /* Not a temp var */ + if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + zval *ret; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, retval_ptr); + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + *EG(return_value_ptr_ptr) = ret; + if (!dup) { + efree(class_name); + } + } else if (!1) { /* Not a temp var */ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { zval *ret; @@ -7036,7 +7072,25 @@ return_by_value: retval_ptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - if (!0) { /* Not a temp var */ + if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + zval *ret; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, retval_ptr); + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + *EG(return_value_ptr_ptr) = ret; + if (!dup) { + efree(class_name); + } + } else if (!0) { /* Not a temp var */ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { zval *ret; @@ -19156,7 +19210,25 @@ return_by_value: retval_ptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); - if (!0) { /* Not a temp var */ + if (EG(ze1_compatibility_mode) && Z_TYPE_P(retval_ptr) == IS_OBJECT) { + zval *ret; + char *class_name; + zend_uint class_name_len; + int dup; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, retval_ptr); + dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC); + if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name); + } + zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name); + ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC); + *EG(return_value_ptr_ptr) = ret; + if (!dup) { + efree(class_name); + } + } else if (!0) { /* Not a temp var */ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF || (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0)) { zval *ret; |