Skip to content

Commit 51d4958

Browse files
committed
Restore ZE1 compatibility mode (Zend Engine part - the modules patches
will follow later today)
1 parent 163f0da commit 51d4958

17 files changed

+474
-17
lines changed

Zend/tests/bug30332.phpt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Bug #30332 (zend.ze1_compatibility_mode isnt fully compatable with array_push())
3+
--INI--
4+
zend.ze1_compatibility_mode=on
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
class x { };
9+
10+
$first = new x;
11+
$second = $first;
12+
$container = array();
13+
array_push($container, $first);
14+
15+
$first->first = " im in the first";
16+
17+
print_r($first);
18+
print_r($second);
19+
print_r($container);
20+
?>
21+
--EXPECTF--
22+
Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 4
23+
24+
Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 5
25+
26+
Strict Standards: Implicit cloning object of class 'x' because of 'zend.ze1_compatibility_mode' in %sbug30332.php on line 7
27+
x Object
28+
(
29+
[first] => im in the first
30+
)
31+
x Object
32+
(
33+
)
34+
Array
35+
(
36+
[0] => x Object
37+
(
38+
)
39+
40+
)

Zend/tests/bug31828.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #31828 (Crash with zend.ze1_compatibility_mode=On)
3+
--INI--
4+
zend.ze1_compatibility_mode=on
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
$o = new stdClass();
9+
$o->id = 77;
10+
$o->name = "Aerospace";
11+
$a[] = $o;
12+
$a = $a[0];
13+
print_r($a);
14+
?>
15+
--EXPECTF--
16+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 2
17+
18+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 5
19+
20+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug31828.php on line 6
21+
stdClass Object
22+
(
23+
[id] => 77
24+
[name] => Aerospace
25+
)

Zend/tests/bug32080.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Bug #32080 (segfault when assigning object to itself with zend.ze1_compatibility_mode=On)
3+
--INI--
4+
zend.ze1_compatibility_mode=on
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
class test { }
9+
$t = new test;
10+
$t = $t; // gives segfault
11+
var_dump($t);
12+
?>
13+
--EXPECTF--
14+
Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 3
15+
16+
Strict Standards: Implicit cloning object of class 'test' because of 'zend.ze1_compatibility_mode' in %sbug32080.php on line 5
17+
object(test)#%d (0) {
18+
}

Zend/tests/bug32852.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Bug #32852 (Crash with singleton and __destruct when zend.ze1_compatibility_mode = On)
3+
--INI--
4+
zend.ze1_compatibility_mode=on
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
class crashme {
9+
private static $instance = null;
10+
11+
public function __construct() {
12+
self::$instance = $this;
13+
}
14+
15+
public function __destruct() {
16+
echo "i'm called\n";
17+
}
18+
19+
public static function singleton() {
20+
if (!isset(self::$instance)) {
21+
self::$instance = new crashme();
22+
}
23+
return self::$instance;
24+
}
25+
}
26+
27+
crashme::singleton();
28+
?>
29+
--EXPECTF--
30+
Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 6
31+
i'm called
32+
33+
Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 15
34+
i'm called
35+
36+
Strict Standards: Implicit cloning object of class 'crashme' because of 'zend.ze1_compatibility_mode' in %sbug32852.php on line 17
37+
i'm called
38+
i'm called

Zend/tests/bug33243.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #33243 (ze1_compatibility_mode does not work as expected)
3+
--INI--
4+
zend.ze1_compatibility_mode=1
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
$a->y->z = 0;
9+
$b = $a; // should perform deep copy of $a
10+
$b->y->z = 1; // hence this should have no effect on $a
11+
var_dump($a);
12+
?>
13+
--EXPECTF--
14+
Strict Standards: Creating default object from empty value in %sbug33243.php on line 2
15+
16+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 3
17+
18+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug33243.php on line 5
19+
object(stdClass)#%d (1) {
20+
["y"]=>
21+
object(stdClass)#%d (1) {
22+
["z"]=>
23+
int(0)
24+
}
25+
}

Zend/tests/bug34712.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Bug #34712 zend.ze1_compatibility_mode = on segfault
3+
--INI--
4+
zend.ze1_compatibility_mode=1
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
class foo {
9+
function foo(&$obj_ref) {
10+
$this->bar = &$obj_ref;
11+
}
12+
}
13+
14+
15+
class bar {
16+
function bar() {
17+
$this->foo = new foo($this);
18+
}
19+
}
20+
21+
$test = new bar;
22+
echo "ok\n";
23+
?>
24+
--EXPECTF--
25+
Strict Standards: Implicit cloning object of class 'foo' because of 'zend.ze1_compatibility_mode' in %sbug34712.php on line 11
26+
27+
Strict Standards: Implicit cloning object of class 'bar' because of 'zend.ze1_compatibility_mode' in %sbug34712.php on line 15
28+
ok

Zend/tests/bug34767.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Bug #34767 (Zend Engine 1 Compatibility not copying objects correctly)
3+
--INI--
4+
zend.ze1_compatibility_mode=1
5+
error_reporting=4095
6+
--FILE--
7+
<?php
8+
$a->y = &new stdClass();
9+
print_r($a);
10+
$b = $a;
11+
$a->y->z = 1;
12+
print_r($b);
13+
?>
14+
--EXPECTF--
15+
16+
Strict Standards: Assigning the return value of new by reference is deprecated in %sbug34767.php on line 2
17+
stdClass Object
18+
(
19+
[y] => stdClass Object
20+
(
21+
)
22+
23+
)
24+
25+
Strict Standards: Implicit cloning object of class 'stdClass' because of 'zend.ze1_compatibility_mode' in %sbug34767.php on line 4
26+
stdClass Object
27+
(
28+
[y] => stdClass Object
29+
(
30+
[z] => 1
31+
)
32+
33+
)

Zend/zend.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static ZEND_INI_MH(OnUpdateErrorReporting)
7777

7878
ZEND_INI_BEGIN()
7979
ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
80+
STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
8081
#ifdef ZEND_MULTIBYTE
8182
STD_ZEND_INI_BOOLEAN("detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals)
8283
#endif

Zend/zend_API.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,25 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_arr
154154
while (param_count-->0) {
155155
zval **value = (zval**)(p-arg_count);
156156

157+
if (EG(ze1_compatibility_mode) && Z_TYPE_PP(value) == IS_OBJECT) {
158+
zval *value_ptr;
159+
char *class_name;
160+
zend_uint class_name_len;
161+
int dup;
162+
163+
dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC);
164+
165+
ALLOC_ZVAL(value_ptr);
166+
*value_ptr = **value;
167+
INIT_PZVAL(value_ptr);
168+
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
169+
if(!dup) {
170+
efree(class_name);
171+
}
172+
value_ptr->value.obj = Z_OBJ_HANDLER_PP(value, clone_obj)(*value TSRMLS_CC);
173+
zval_ptr_dtor(value);
174+
*value = value_ptr;
175+
}
157176
*(argument_array++) = value;
158177
arg_count--;
159178
}

Zend/zend_execute.c

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -554,11 +554,30 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode
554554
FREE_OP(free_value);
555555
return;
556556
}
557-
557+
558558
/* here we are sure we are dealing with an object */
559559

560560
/* separate our value if necessary */
561-
if (value_op->op_type == IS_TMP_VAR) {
561+
if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) {
562+
zval *orig_value = value;
563+
char *class_name;
564+
zend_uint class_name_len;
565+
int dup;
566+
567+
ALLOC_ZVAL(value);
568+
*value = *orig_value;
569+
value->is_ref = 0;
570+
value->refcount = 0;
571+
dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC);
572+
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
573+
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
574+
}
575+
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
576+
value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC);
577+
if(!dup) {
578+
efree(class_name);
579+
}
580+
} else if (value_op->op_type == IS_TMP_VAR) {
562581
zval *orig_value = value;
563582

564583
ALLOC_ZVAL(value);
@@ -701,7 +720,55 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
701720
goto done_setting_var;
702721
}
703722

704-
if (PZVAL_IS_REF(variable_ptr)) {
723+
if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) {
724+
char *class_name;
725+
zend_uint class_name_len;
726+
int dup;
727+
728+
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
729+
730+
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
731+
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
732+
} else if (PZVAL_IS_REF(variable_ptr)) {
733+
if (variable_ptr != value) {
734+
zend_uint refcount = variable_ptr->refcount;
735+
zval garbage;
736+
737+
if (type != IS_TMP_VAR) {
738+
value->refcount++;
739+
}
740+
garbage = *variable_ptr;
741+
*variable_ptr = *value;
742+
variable_ptr->refcount = refcount;
743+
variable_ptr->is_ref = 1;
744+
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
745+
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
746+
if (type != IS_TMP_VAR) {
747+
value->refcount--;
748+
}
749+
zendi_zval_dtor(garbage);
750+
}
751+
} else {
752+
if (variable_ptr != value) {
753+
value->refcount++;
754+
variable_ptr->refcount--;
755+
if (variable_ptr->refcount == 0) {
756+
zendi_zval_dtor(*variable_ptr);
757+
} else {
758+
ALLOC_ZVAL(variable_ptr);
759+
*variable_ptr_ptr = variable_ptr;
760+
}
761+
*variable_ptr = *value;
762+
INIT_PZVAL(variable_ptr);
763+
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
764+
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
765+
zval_ptr_dtor(&value);
766+
}
767+
}
768+
if (!dup) {
769+
efree(class_name);
770+
}
771+
} else if (PZVAL_IS_REF(variable_ptr)) {
705772
if (variable_ptr!=value) {
706773
zend_uint refcount = variable_ptr->refcount;
707774
zval garbage;
@@ -791,9 +858,34 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
791858

792859
static inline void zend_receive(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
793860
{
794-
(*variable_ptr_ptr)->refcount--;
795-
*variable_ptr_ptr = value;
796-
value->refcount++;
861+
zval *variable_ptr = *variable_ptr_ptr;
862+
863+
if (EG(ze1_compatibility_mode) && Z_TYPE_P(value) == IS_OBJECT) {
864+
char *class_name;
865+
zend_uint class_name_len;
866+
int dup;
867+
868+
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
869+
870+
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
871+
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
872+
} else {
873+
variable_ptr->refcount--;
874+
ALLOC_ZVAL(variable_ptr);
875+
*variable_ptr_ptr = variable_ptr;
876+
*variable_ptr = *value;
877+
INIT_PZVAL(variable_ptr);
878+
zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
879+
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
880+
}
881+
if (!dup) {
882+
efree(class_name);
883+
}
884+
} else {
885+
variable_ptr->refcount--;
886+
*variable_ptr_ptr = value;
887+
value->refcount++;
888+
}
797889
}
798890

799891
/* Utility Functions for Extensions */

Zend/zend_execute.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,15 @@ static inline int i_zend_is_true(zval *op)
116116
break;
117117
}
118118
}
119+
120+
if(EG(ze1_compatibility_mode)) {
121+
result = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0);
122+
} else {
123+
result = 1;
124+
}
125+
} else {
126+
result = 1;
119127
}
120-
result = 1;
121128
break;
122129
default:
123130
result = 0;

0 commit comments

Comments
 (0)