Skip to content

Deprecate dynamic property creation with #[AllowDynamicProperties] escape hatch #7571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Zend/Optimizer/sccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,9 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o

/* Don't try to propagate assignments to (potentially) typed properties. We would
* need to deal with errors and type conversions first. */
if (!var_info->ce || (var_info->ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
// TODO: Distinguish dynamic and declared property assignments here?
if (!var_info->ce || (var_info->ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) ||
!(var_info->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
SET_RESULT_BOT(result);
SET_RESULT_BOT(op1);
return;
Expand Down
14 changes: 8 additions & 6 deletions Zend/Optimizer/zend_inference.c
Original file line number Diff line number Diff line change
Expand Up @@ -4842,15 +4842,17 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
return 1;
}

if (op_array->scope != ce && ce->default_properties_count) {
zend_property_info *prop_info =
zend_hash_find_ptr(&ce->properties_info, prop_name);
if (prop_info && (!(prop_info->flags & ZEND_ACC_PUBLIC)
|| ZEND_TYPE_IS_SET(prop_info->type))) {
zend_property_info *prop_info =
zend_hash_find_ptr(&ce->properties_info, prop_name);
if (prop_info) {
if (ZEND_TYPE_IS_SET(prop_info->type)) {
return 1;
}
return !(prop_info->flags & ZEND_ACC_PUBLIC)
&& prop_info->ce != op_array->scope;
} else {
return !(ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES);
}
return 0;
}
return 1;
case ZEND_ROPE_INIT:
Expand Down
11 changes: 11 additions & 0 deletions Zend/tests/allow_dynamic_properties_on_interface.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
#[AllowDynamicProperties] cannot be applied to interface
--FILE--
<?php

#[AllowDynamicProperties]
interface Test {}

?>
--EXPECTF--
Fatal error: Cannot apply #[AllowDynamicProperties] to interface in %s on line %d
11 changes: 11 additions & 0 deletions Zend/tests/allow_dynamic_properties_on_trait.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
#[AllowDynamicProperties] cannot be applied to trait
--FILE--
<?php

#[AllowDynamicProperties]
trait Test {}

?>
--EXPECTF--
Fatal error: Cannot apply #[AllowDynamicProperties] to trait in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/anon/003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ reusing anonymous classes
<?php
while (@$i++<10) {
var_dump(new class($i) {

public $i;
public function __construct($i) {
$this->i = $i;
}
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/assign_to_obj_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function &a($i) {
}

class A {
public $a;
public function test() {
$this->a = a(1);
unset($this->a);
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug27268.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Bug #27268 (Bad references accentuated by clone)
--FILE--
<?php
#[AllowDynamicProperties]
class A
{
public function &getA()
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug30162.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Bug #30162 (Catching exception in constructor couses lose of $this)
--FILE--
<?php
#[AllowDynamicProperties]
class FIIFO {

public function __construct() {
Expand All @@ -11,6 +12,7 @@ class FIIFO {

}

#[AllowDynamicProperties]
class hariCow extends FIIFO {

public function __construct() {
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug38779_1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Bug #38779 (engine crashes when require()'ing file with syntax error through use
<?php

class Loader {
public $context;
private $position;
private $data;
public function stream_open($path, $mode, $options, &$opened_path) {
Expand Down
6 changes: 2 additions & 4 deletions Zend/tests/bug47343.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Bug #47343 (gc_collect_cycles causes a segfault when called within a destructor
<?php
class A
{
public $data = [];
public function __destruct()
{
gc_collect_cycles();
Expand All @@ -20,10 +21,7 @@ class A

class B
{
public function __construct($A)
{
$this->A = $A;
}
public function __construct(public $A) {}

public function __destruct()
{
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug49893.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class A {
}
}
class B {
public $a;
function __construct() {
$this->a = new A();
throw new Exception("1");
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug51822.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class DestructableObject

class DestructorCreator
{
public $test;
public function __destruct()
{
$this->test = new DestructableObject;
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug54268.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class DestructableObject
}
class DestructorCreator
{
public $test;
public function __destruct()
{
$this->test = new DestructableObject;
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug55305.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Bug #55305 (ref lost: 1st ref instantiated in class def, 2nd ref made w/o instantiating)
--FILE--
<?php
#[AllowDynamicProperties]
class Foo {
var $foo = "test";
}
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug60536_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Y extends X {
return ++$this->x;
}
}
#[AllowDynamicProperties]
class Z extends Y {
function __construct() {
return ++$this->x;
Expand Down
33 changes: 14 additions & 19 deletions Zend/tests/bug60833.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,30 @@ Bug #60833 (self, parent, static behave inconsistently case-sensitive)
class A {
static $x = "A";
function testit() {
$this->v1 = new sELF;
$this->v2 = new SELF;
var_dump(new sELF);
var_dump(new SELF);
}
}

class B extends A {
static $x = "B";
function testit() {
PARENT::testit();
$this->v3 = new sELF;
$this->v4 = new PARENT;
$this->v4 = STATIC::$x;
var_dump(new sELF);
var_dump(new PARENT);
var_dump(STATIC::$x);
}
}
$t = new B();
$t->testit();
var_dump($t);
?>
--EXPECTF--
object(B)#%d (4) {
["v1"]=>
object(A)#%d (0) {
}
["v2"]=>
object(A)#%d (0) {
}
["v3"]=>
object(B)#%d (0) {
}
["v4"]=>
string(1) "B"
--EXPECT--
object(A)#2 (0) {
}
object(A)#2 (0) {
}
object(B)#2 (0) {
}
object(A)#2 (0) {
}
string(1) "B"
1 change: 1 addition & 0 deletions Zend/tests/bug63462.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Test script to verify that magic methods should be called only once when accessi
Marco Pivetta <ocramius@gmail.com>
--FILE--
<?php
#[AllowDynamicProperties]
class Test {
public $publicProperty;
protected $protectedProperty;
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug64821.1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Bug #64821 Custom Exceptions crash when internal properties overridden (variatio
--FILE--
<?php

#[AllowDynamicProperties]
class a extends exception {
public function __construct() {
$this->message = NULL;
Expand Down
4 changes: 4 additions & 0 deletions Zend/tests/bug64960.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ $a['waa'];
--EXPECTF--
Notice: ob_end_flush(): Failed to delete and flush buffer. No buffer to delete or flush in %sbug64960.php on line 3

Deprecated: Creation of dynamic property Exception::$_trace is deprecated in %s on line %d

Deprecated: Creation of dynamic property Exception::$_trace is deprecated in %s on line %d

Fatal error: Uncaught Exception in %sbug64960.php:19
Stack trace:
#0 [internal function]: {closure}(8, 'ob_end_clean():...', '%s', 9)
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug65911.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class A {}

class B
{
public $foo;
public function go()
{
$this->foo = 'bar';
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug66609.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Bar {
return $foo->foo;
}
}
#[AllowDynamicProperties]
class Foo {
public function __get($x) {
global $bar;
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug69446.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zend.enable_gc = 1
--FILE--
<?php
$bar = NULL;
#[AllowDynamicProperties]
class bad {
public function __destruct() {
global $bar;
Expand Down
3 changes: 3 additions & 0 deletions Zend/tests/bug70223.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Bug #70223 (Incrementing value returned by magic getter)
--FILE--
<?php

// Note that this actually writes to dynamic property A::$f.
// Increment goes through __set(), not __get() by reference!
#[AllowDynamicProperties]
class A {

private $foo = 0;
Expand Down
4 changes: 3 additions & 1 deletion Zend/tests/bug70397.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ $f = function () {
yield $this->value;
};

var_dump($f->call(new class {})->current());
var_dump($f->call(new class {
public $value;
})->current());

?>
--EXPECT--
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug70805.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ Bug #70805 (Segmentation faults whilst running Drupal 8 test suite)
--FILE--
<?php
class A {
public $b;
}

class B {
public $a;
}

class C {
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug70805_1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ zend.enable_gc = 1
--FILE--
<?php
class A {
public $b;
}

class B {
public $a;
}

class C {
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug70805_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ zend.enable_gc = 1
--FILE--
<?php
class A {
public $b;
}

class B {
public $a;
}

class C {
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug71859.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Bug #71859 (zend_objects_store_call_destructors operates on realloced memory, cr
--FILE--
<?php
class constructs_in_destructor {
public $a;
public function __destruct() {
//We are now in zend_objects_store_call_destructors
//This causes a realloc in zend_objects_store_put
Expand Down
13 changes: 7 additions & 6 deletions Zend/tests/bug72101.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PHPUnit_Framework_MockObject_InvocationMocker {

class PHPUnit_Framework_MockObject_Matcher {
public $stub = null;
public $methodNameMatcher;
public function invoked($invocation) {
return $this->stub->invoke($invocation);
}
Expand Down Expand Up @@ -77,10 +78,10 @@ $foo->bar($a, $b, $c);
--EXPECTF--
Fatal error: Uncaught Error: Class "DoesNotExists" not found in %s:%d
Stack trace:
#0 %sbug72101.php(8): {closure}(2, 'MethodCallbackB...', '%s', 8)
#1 %sbug72101.php(27): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#2 %sbug72101.php(19): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#3 %sbug72101.php(52): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#4 %sbug72101.php(72): Mock_MethodCallbackByReference_7b180d26->bar(0, 0, 0)
#0 %sbug72101.php(%d): {closure}(2, 'MethodCallbackB...', '%s', 8)
#1 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Stub_ReturnCallback->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#2 %sbug72101.php(%d): PHPUnit_Framework_MockObject_Matcher->invoked(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#3 %sbug72101.php(%d): PHPUnit_Framework_MockObject_InvocationMocker->invoke(Object(PHPUnit_Framework_MockObject_Invocation_Static))
#4 %sbug72101.php(%d): Mock_MethodCallbackByReference_7b180d26->bar(0, 0, 0)
#5 {main}
thrown in %sbug72101.php on line 61
thrown in %sbug72101.php on line %d
1 change: 1 addition & 0 deletions Zend/tests/bug78010.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ memory_limit=2G
--FILE--
<?php

#[AllowDynamicProperties]
class foo
{
public function __construct()
Expand Down
3 changes: 2 additions & 1 deletion Zend/tests/bug78340.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ Bug #78340: Include of stream wrapper not reading whole file
<?php

class lib {
public $context;
public static $files= [];

private $bytes, $pos;
private $bytes, $pos, $ino;

function stream_open($path, $mode, $options, $opened_path) {
$this->bytes= self::$files[$path];
Expand Down
2 changes: 2 additions & 0 deletions Zend/tests/bug78379.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ Bug #78379 (Cast to object confuses GC, causes crash)
--FILE--
<?php
class C {
public $p;
public function __construct() {
$this->p = (object)["x" => [1]];
}
}
#[AllowDynamicProperties]
class E {
}
$e = new E;
Expand Down
1 change: 1 addition & 0 deletions Zend/tests/bug78379_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Bug #78379.2 (Cast to object confuses GC, causes crash)
--FILE--
<?php
#[AllowDynamicProperties]
class E {}
function f() {
$e1 = new E;
Expand Down
Loading