Browse Source

Remove assignment of new by reference

pull/1026/head
Nikita Popov 11 years ago
parent
commit
4d3e4d3bf9
  1. 1
      NEWS
  2. 1
      UPGRADING
  3. 29
      Zend/tests/bug45178.phpt
  4. 10
      Zend/zend_compile.c
  5. 3
      Zend/zend_compile.h
  6. 2
      Zend/zend_language_parser.y
  7. 10
      Zend/zend_vm_def.h
  8. 40
      Zend/zend_vm_execute.h
  9. 5
      ext/standard/tests/serialize/bug31402.phpt
  10. 48
      tests/classes/new_001.phpt
  11. 7
      tests/lang/bug20175.phpt
  12. 6
      tests/lang/bug22231.phpt
  13. 4
      tests/lang/bug22510.phpt
  14. 13
      tests/lang/engine_assignExecutionOrder_007.phpt

1
NEWS

@ -37,6 +37,7 @@
. Removed scoped calls of non-static methods from an incompatible $this
context. (Nikita)
. Removed support for #-style comments in ini files. (Nikita)
. Removed support for assigning the result of new by reference. (Nikita)
. Invalid octal literals in source code now produce compile errors, fixes PHPSadness #31. (Andrea)
- Date:

1
UPGRADING

@ -54,6 +54,7 @@ PHP X.Y UPGRADE NOTES
. zend_function.common.num_args don't include the variadic argument anymore.
. ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an
output buffer is created in an output buffer handler.
. Removed support for assigning the result of new by reference.
. Removed support for scoped calls to non-static methods from an incompatible
$this context. See details in https://wiki.php.net/rfc/incompat_ctx.
. Removed support for #-style comments in ini files. Use ;-style comments

29
Zend/tests/bug45178.phpt

@ -1,29 +0,0 @@
--TEST--
Bug #45178 memory corruption on assignment result of "new" by reference
--FILE--
<?php
class Foo {
function __construct() {
$this->error = array($this,$this);
}
}
$a =& new Foo();
class Bar {
function __construct() {
$this->_rme2 = $this;
}
}
$b =& new Bar();
$b->_rme2 = 0;
var_dump($b);
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %sbug45178.php on line 7
Deprecated: Assigning the return value of new by reference is deprecated in %sbug45178.php on line 15
object(Bar)#%d (1) {
["_rme2"]=>
int(0)
}

10
Zend/zend_compile.c

@ -2341,9 +2341,6 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
if (zend_is_call(source_ast)) {
opline->extended_value = ZEND_RETURNS_FUNCTION;
} else if (source_ast->kind == ZEND_AST_NEW) {
zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");
opline->extended_value = ZEND_RETURNS_NEW;
}
}
/* }}} */
@ -6361,11 +6358,8 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
if (type == BP_VAR_W || type == BP_VAR_REF
|| type == BP_VAR_RW || type == BP_VAR_UNSET
) {
/* For BC reasons =& new Foo is allowed */
if (type != BP_VAR_REF || ast->kind != ZEND_AST_NEW) {
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot use temporary expression in write context");
}
zend_error_noreturn(E_COMPILE_ERROR,
"Cannot use temporary expression in write context");
}
zend_compile_expr(result, ast);

3
Zend/zend_compile.h

@ -858,8 +858,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
#define ZEND_RETURNS_FUNCTION 1<<0
#define ZEND_RETURNS_NEW 1<<1
#define ZEND_RETURNS_VALUE 1<<2
#define ZEND_RETURNS_VALUE 1<<1
#define ZEND_FAST_RET_TO_CATCH 1
#define ZEND_FAST_RET_TO_FINALLY 2

2
Zend/zend_language_parser.y

@ -769,8 +769,6 @@ expr_without_variable:
{ $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); }
| variable '=' '&' variable
{ $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
| variable '=' '&' new_expr
{ $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
| T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); }
| variable T_PLUS_EQUAL expr
{ $$ = zend_ast_create_assign_op(ZEND_ASSIGN_ADD, $1, $3); }

10
Zend/zend_vm_def.h

@ -1818,10 +1818,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
HANDLE_EXCEPTION();
}
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ASSIGN);
} else if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!OP2_FREE) {
PZVAL_LOCK(value_ptr);
}
}
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
@ -1840,12 +1836,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!OP2_FREE) {
Z_DELREF_P(variable_ptr);
}
}
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}

40
Zend/zend_vm_execute.h

@ -14200,10 +14200,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!(free_op2 != NULL)) {
PZVAL_LOCK(value_ptr);
}
}
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@ -14222,12 +14218,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!(free_op2 != NULL)) {
Z_DELREF_P(variable_ptr);
}
}
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}
@ -16210,10 +16200,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!0) {
PZVAL_LOCK(value_ptr);
}
}
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@ -16232,12 +16218,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!0) {
Z_DELREF_P(variable_ptr);
}
}
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}
@ -27366,10 +27346,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!(free_op2 != NULL)) {
PZVAL_LOCK(value_ptr);
}
}
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
@ -27388,12 +27364,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!(free_op2 != NULL)) {
Z_DELREF_P(variable_ptr);
}
}
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}
@ -30132,10 +30102,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
HANDLE_EXCEPTION();
}
return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!0) {
PZVAL_LOCK(value_ptr);
}
}
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
@ -30154,12 +30120,6 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
if (!0) {
Z_DELREF_P(variable_ptr);
}
}
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
}

5
ext/standard/tests/serialize/bug31402.phpt

@ -1,7 +1,7 @@
--TEST--
Bug #31402 (unserialize() generates references when it should not)
--INI--
error_reporting=E_ALL&~E_STRICT&~E_DEPRECATED
error_reporting=E_ALL
--FILE--
<?php
@ -19,7 +19,8 @@ class TestY {
function __construct() {
$this->A[1] = new TestX(1);
$this->A[2] = & new TestX(2);
$obj = new TestX(2);
$this->A[2] = & $obj;
$this->A[3] = & $this->A[2];
$this->B = $this->A[1];
}

48
tests/classes/new_001.phpt

@ -1,48 +0,0 @@
--TEST--
Confirm difference between assigning new directly and by reference.
--INI--
error_reporting=E_ALL | E_DEPRECATED
--FILE--
<?php
echo "Compile-time strict error message should precede this.\n";
class Inc
{
private static $counter = 0;
function __construct()
{
$this->id = ++Inc::$counter;
}
}
$f = new Inc();
$k =& $f;
echo "\$f initially points to the first object:\n";
var_dump($f);
echo "Assigning new object directly to \$k affects \$f:\n";
$k = new Inc();
var_dump($f);
echo "Assigning new object by ref to \$k removes it from \$f's reference set, so \$f is unchanged:\n";
$k =& new Inc();
var_dump($f);
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %s on line 23
Compile-time strict error message should precede this.
$f initially points to the first object:
object(Inc)#%d (1) {
["id"]=>
int(1)
}
Assigning new object directly to $k affects $f:
object(Inc)#%d (1) {
["id"]=>
int(2)
}
Assigning new object by ref to $k removes it from $f's reference set, so $f is unchanged:
object(Inc)#%d (1) {
["id"]=>
int(2)
}

7
tests/lang/bug20175.phpt

@ -1,9 +1,7 @@
--TEST--
Bug #20175 (Static vars can't store ref to new instance)
--SKIPIF--
<?php if (version_compare(zend_version(),'2.0.0-dev','<')) die('skip ZE1 does not have static class members'); ?>
--INI--
error_reporting=E_ALL | E_STRICT | E_DEPRECATED
error_reporting=E_ALL
--FILE--
<?php
print zend_version()."\n";
@ -114,7 +112,7 @@ class oop_test {
function oop_static() {
echo "oop_static()\n";
if (!isset(self::$oop_value)) {
self::$oop_value = & new oop_class;
self::$oop_value = new oop_class;
}
echo self::$oop_value->oop_name;
}
@ -139,7 +137,6 @@ $oop_tester = new oop_test; // repeated.
print $oop_tester->oop_static()."\n";
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %s.php on line %d
%s
foo_static()
foo_global()

6
tests/lang/bug22231.phpt

@ -1,7 +1,7 @@
--TEST--
Bug #22231 (segfault when returning a global variable by reference)
--INI--
error_reporting=E_ALL | E_DEPRECATED
error_reporting=E_ALL
--FILE--
<?php
class foo {
@ -9,7 +9,8 @@ class foo {
}
function &foo(){
$GLOBALS['foo'] = &new foo();
$obj = new foo();
$GLOBALS['foo'] = &$obj;
return $GLOBALS['foo'];
}
$bar = &foo();
@ -27,7 +28,6 @@ $foo = &foo();
var_dump($foo->fubar);
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %s on line %d
object(foo)#%d (1) {
["fubar"]=>
string(5) "fubar"

4
tests/lang/bug22510.phpt

@ -76,7 +76,8 @@ function ok3(&$bar) {
$bar->run3();
}
$bar = &new bar();
$foo = new bar();
$bar =& $foo;
ok1($bar);
$bar->instance->finalize();
print "done!\n";
@ -91,7 +92,6 @@ $bar->instance->finalize();
print "I'm alive!\n";
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %s on line %d
ok1
bar::run1
foo::method1

13
tests/lang/engine_assignExecutionOrder_007.phpt

@ -1,22 +1,17 @@
--TEST--
Check key execution order with &new.
Check key execution order with new.
--FILE--
<?php
$a[2][3] = 'stdClass';
$a[$i=0][++$i] =& new $a[++$i][++$i];
$a[$i=0][++$i] = new $a[++$i][++$i];
print_r($a);
$o = new stdClass;
$o->a =& new $a[$i=2][++$i];
$o->a->b =& new $a[$i=2][++$i];
$o->a = new $a[$i=2][++$i];
$o->a->b = new $a[$i=2][++$i];
print_r($o);
?>
--EXPECTF--
Deprecated: Assigning the return value of new by reference is deprecated in %s.php on line 3
Deprecated: Assigning the return value of new by reference is deprecated in %s.php on line 7
Deprecated: Assigning the return value of new by reference is deprecated in %s.php on line 8
Array
(
[2] => Array

Loading…
Cancel
Save