]> granicus.if.org Git - php/commitdiff
Restore ZE1 compatibility mode (Zend Engine part - the modules patches
authorZeev Suraski <zeev@php.net>
Mon, 5 Jun 2006 13:58:52 +0000 (13:58 +0000)
committerZeev Suraski <zeev@php.net>
Mon, 5 Jun 2006 13:58:52 +0000 (13:58 +0000)
will follow later today)

17 files changed:
Zend/tests/bug30332.phpt [new file with mode: 0644]
Zend/tests/bug31828.phpt [new file with mode: 0644]
Zend/tests/bug32080.phpt [new file with mode: 0644]
Zend/tests/bug32852.phpt [new file with mode: 0644]
Zend/tests/bug33243.phpt [new file with mode: 0755]
Zend/tests/bug34712.phpt [new file with mode: 0755]
Zend/tests/bug34767.phpt [new file with mode: 0755]
Zend/zend.c
Zend/zend_API.c
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_objects.c
Zend/zend_operators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug30332.phpt b/Zend/tests/bug30332.phpt
new file mode 100644 (file)
index 0000000..e247849
--- /dev/null
@@ -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 (file)
index 0000000..a3cc454
--- /dev/null
@@ -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 (file)
index 0000000..a96c8bf
--- /dev/null
@@ -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 (file)
index 0000000..38cea6f
--- /dev/null
@@ -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 (executable)
index 0000000..bb5d77c
--- /dev/null
@@ -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 (executable)
index 0000000..db7860c
--- /dev/null
@@ -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 (executable)
index 0000000..45af9f9
--- /dev/null
@@ -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
+        )
+
+)
index d63ec97198c69332cb79a23dcfc1e4be107a6583..e12598e63d8286dcc05fe83b50a154a088d87884 100644 (file)
@@ -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
index b87da8884ea780556bc76cd09061f36e27c2946e..b32b9eb47d72a68d9e2d5ead885562197148c040 100644 (file)
@@ -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--;
        }
index f7a19a5845c8df7fc0f725961d59fa0b3934fe35..99fb7ac7adc211410a40a346d08373b0a1be917e 100644 (file)
@@ -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 */
index a76c6885139c272046b61c1465d10c25f74b772d..11b92bd68032bf504483b5a06c86d23b4aae6bfb 100644 (file)
@@ -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;
index 7b9f1417754677bb42ba71cffba3c3acde370e08..e7d78c40293be6a09c9e62938fb0b22c609bc8f9 100644 (file)
@@ -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;
        }
 }
index d1bda5b0646442cdebbd0db732837230e6b84e8e..72d045e2814e9748b23ace2c6e9680ea1cac5620 100644 (file)
@@ -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;
index e2d86e8fe820df842f24c4bca6f7073846be245b..6dc4ba4aa356464d4b6f7bf3c13489f245b1612b 100644 (file)
@@ -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;
 
index 65a224840a955a2d9bee2728751e6b81dca0ca21..37f412fe758fa5f1dac200ccc8c52ebc11a8f65a 100644 (file)
@@ -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;
                        }
index b69a7a6017581858aabf7f6b70c77acd2f50e418..5295320de93338ce0ae3243ec9a483bac3388a76 100644 (file)
@@ -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;
index 0300a92c45d1ad69960af2a95381fa5af183f9d1..8dc247d4fd0afd49ed8b5d08c8527b1447ca85e6 100644 (file)
@@ -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;