Deprecate implicit dynamic properties

Writing to a proprety that hasn't been declared is deprecated,
unless the class uses the #[AllowDynamicProperties] attribute or
defines __get()/__set().

RFC: https://wiki.php.net/rfc/deprecate_dynamic_properties
This commit is contained in:
Nikita Popov 2021-10-11 15:49:27 +02:00
parent 35a01f86e0
commit 902d64390e
201 changed files with 583 additions and 177 deletions

View file

@ -48,6 +48,16 @@ PHP 8.2 UPGRADE NOTES
========================================
- Core:
. Creation of dynamic properties is deprecated, unless the class opts in by
using the #[AllowDynamicProperties] attribute. stdClass allows dynamic
properties. Usage of __get()/__set() is not affected by this change. A
dynamic properties deprecation warning can be addressed by:
- Declaring the property (preferred).
- Adding the #[AllowDynamicProperties] attribute to the class (which also
applies to all child classes).
- Using a WeakMap if you wish to associate additional data with an object
you do not own.
. Callables that are not accepted by the $callable() syntax (but are accepted
by call_user_func) are deprecated. In particular:

View file

@ -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;

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -8,6 +8,7 @@ function &a($i) {
}
class A {
public $a;
public function test() {
$this->a = a(1);
unset($this->a);

View file

@ -2,6 +2,7 @@
Bug #27268 (Bad references accentuated by clone)
--FILE--
<?php
#[AllowDynamicProperties]
class A
{
public function &getA()

View file

@ -2,6 +2,7 @@
Bug #30162 (Catching exception in constructor couses lose of $this)
--FILE--
<?php
#[AllowDynamicProperties]
class FIIFO {
public function __construct() {
@ -11,6 +12,7 @@ class FIIFO {
}
#[AllowDynamicProperties]
class hariCow extends FIIFO {
public function __construct() {

View file

@ -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) {

View file

@ -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();
@ -20,10 +21,7 @@ class A
class B
{
public function __construct($A)
{
$this->A = $A;
}
public function __construct(public $A) {}
public function __destruct()
{

View file

@ -12,6 +12,7 @@ class A {
}
}
class B {
public $a;
function __construct() {
$this->a = new A();
throw new Exception("1");

View file

@ -12,6 +12,7 @@ class DestructableObject
class DestructorCreator
{
public $test;
public function __destruct()
{
$this->test = new DestructableObject;

View file

@ -20,6 +20,7 @@ class DestructableObject
}
class DestructorCreator
{
public $test;
public function __destruct()
{
$this->test = new DestructableObject;

View file

@ -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";
}

View file

@ -12,6 +12,7 @@ class Y extends X {
return ++$this->x;
}
}
#[AllowDynamicProperties]
class Z extends Y {
function __construct() {
return ++$this->x;

View file

@ -5,8 +5,8 @@ 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);
}
}
@ -14,26 +14,21 @@ 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"

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -6,6 +6,7 @@ class A {}
class B
{
public $foo;
public function go()
{
$this->foo = 'bar';

View file

@ -10,6 +10,7 @@ class Bar {
return $foo->foo;
}
}
#[AllowDynamicProperties]
class Foo {
public function __get($x) {
global $bar;

View file

@ -5,6 +5,7 @@ zend.enable_gc = 1
--FILE--
<?php
$bar = NULL;
#[AllowDynamicProperties]
class bad {
public function __destruct() {
global $bar;

View file

@ -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;

View file

@ -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--

View file

@ -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 {

View file

@ -5,9 +5,11 @@ zend.enable_gc = 1
--FILE--
<?php
class A {
public $b;
}
class B {
public $a;
}
class C {

View file

@ -5,9 +5,11 @@ zend.enable_gc = 1
--FILE--
<?php
class A {
public $b;
}
class B {
public $a;
}
class C {

View file

@ -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

View file

@ -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);
}
@ -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

View file

@ -5,6 +5,7 @@ memory_limit=2G
--FILE--
<?php
#[AllowDynamicProperties]
class foo
{
public function __construct()

View file

@ -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];

View file

@ -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;

View file

@ -2,6 +2,7 @@
Bug #78379.2 (Cast to object confuses GC, causes crash)
--FILE--
<?php
#[AllowDynamicProperties]
class E {}
function f() {
$e1 = new E;

View file

@ -4,6 +4,7 @@ Bug #78589: Memory leak with GC + __destruct()
<?php
class Test {
public $foo;
public function __destruct() {}
}

View file

@ -3,6 +3,7 @@ Bug #79477: casting object into array creates references
--FILE--
<?php
#[AllowDynamicProperties]
class Test {
public $prop = 'default value';
}

View file

@ -3,6 +3,7 @@ Bug #79862: Public non-static property in child should take priority over privat
--FILE--
<?php
#[AllowDynamicProperties]
class a {
private static $prop1;
private static $prop2;

View file

@ -5,6 +5,7 @@ memory_limit=5M
report_memleaks=0
--FILE--
<?php
#[AllowDynamicProperties]
class X {
public $x;
public function __construct() { $this->x = [$this]; }

View file

@ -5,6 +5,7 @@ Closure 020: Trying to access private property outside class
class foo {
private $test = 3;
public $a;
public function x() {
$a = &$this;

View file

@ -4,6 +4,7 @@ Closure 026: Assigning a closure object to an array in $this
<?php
class foo {
public $a;
public function __construct() {
$a =& $this;

View file

@ -0,0 +1,47 @@
--TEST--
Dynamic properties deprecation
--FILE--
<?php
class Test {}
$obj = new Test;
$obj->prop = 1; // Deprecated
$obj->prop = 1; // Ok
$obj->prop2 += 1; // Deprecated
$obj->prop2 += 1; // Ok
$obj->prop3++; // Deprecated
$obj->prop3++; // Ok
$obj->prop4[] = 1; // Deprecated
$obj->prop4[] = 1; // Ok
isset($obj->prop5); // Ok
unset($obj->prop6); // Ok
// stdClass should not throw deprecation.
$obj = new stdClass;
$obj->prop = 1;
// Classes with #[AllowDynamicProperties] should not throw deprecation.
#[AllowDynamicProperties]
class Test2 {}
class Test3 extends Test2 {}
$obj = new Test2;
$obj->prop = 1;
$obj = new Test3;
$obj->prop = 1;
?>
--EXPECTF--
Deprecated: Creation of dynamic property Test::$prop is deprecated in %s on line %d
Deprecated: Creation of dynamic property Test::$prop2 is deprecated in %s on line %d
Warning: Undefined property: Test::$prop2 in %s on line %d
Deprecated: Creation of dynamic property Test::$prop3 is deprecated in %s on line %d
Warning: Undefined property: Test::$prop3 in %s on line %d
Deprecated: Creation of dynamic property Test::$prop4 is deprecated in %s on line %d

View file

@ -4,6 +4,7 @@ Exception in stream wrapper + __call
<?php
class Loader {
public $context;
function stream_open() {
return true;
}

View file

@ -5,9 +5,10 @@ Context switches are prevented during GC collect cycles
$fiber = new Fiber(function () {
call_user_func(function () {
$a = new class () {};
$a = new class { public $next; };
$b = new class () {
$b = new class {
public $next;
public function __destruct() {
Fiber::suspend();
}

View file

@ -13,6 +13,8 @@ class Test {
var_dump(get_object_vars($this));
}
}
#[AllowDynamicProperties]
class Test2 extends Test {
}

View file

@ -126,13 +126,14 @@ function test_pow() {
test_pow();
class Y {
public $x;
function __toString() {
return "y";
}
}
function test_concat() {
$x = new Y;
$x->x= $x;
$x->x = $x;
@$x .= "x";
$n = gc_collect_cycles();
echo ".=\t$n\n";

View file

@ -3,6 +3,7 @@ Object properties HT may need to be removed from nested data
--FILE--
<?php
#[AllowDynamicProperties]
class Test {
public function __destruct() {
$GLOBALS['x'] = $this;

View file

@ -4,6 +4,8 @@ A generator iterator wrapper involved in a cycle should not leak
<?php
class Test {
private $gen1;
private $gen2;
public function method() {
$this->gen1 = (function () {
yield 1;

View file

@ -3,6 +3,7 @@ get_mangled_object_vars() function
--FILE--
<?php
#[AllowDynamicProperties]
class A {
public $pub = 1;
protected $prot = 2;
@ -19,6 +20,7 @@ $obj->{"6"} = 6;
var_export(get_mangled_object_vars($obj));
echo "\n";
#[AllowDynamicProperties]
class AO extends ArrayObject {
private $priv = 1;
}

View file

@ -4,7 +4,7 @@
$a = 1;
$b = 2;
$c = array( 'c' => 3, );
class d { public function __construct() { $this->d = 4; } };
class d { public $d = 4; };
$d = new d;
?>

View file

@ -77,6 +77,7 @@ try {
try {
var_dump((function() { return new class {
public $foo;
function __construct() { $this->foo = new stdClass; }
function __destruct() { throw new Exception; }
}; })()->foo++);
@ -92,6 +93,7 @@ try {
try {
var_dump((function() { return new class {
public $bar;
function __construct() { $this->bar = new stdClass; }
function &__get($x) { return $this->bar; }
function __destruct() { throw new Exception; }
@ -115,6 +117,7 @@ try {
try {
var_dump(++(function() { return new class {
public $bar;
function __construct() { $this->bar = new stdClass; }
function &__get($x) { return $this->bar; }
function __destruct() { throw new Exception; }
@ -143,6 +146,7 @@ try {
try {
var_dump((new class {
public $foo;
function __construct() { $this->foo = new stdClass; }
function __destruct() { throw new Exception; }
})->foo);
@ -168,6 +172,7 @@ try {
try {
var_dump(isset((new class {
public $foo;
function __construct() { $this->foo = new stdClass; }
function __destruct() { throw new Exception; }
})->foo->bar));
@ -278,14 +283,22 @@ caught Exception 2
caught Exception 3
caught Exception 4
caught Exception 5
Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
caught Exception 6
caught Exception 7
caught Exception 8
caught Exception 9
caught Exception 10
Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
caught Exception 11
Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
caught Exception 12
caught Exception 13
Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
caught Exception 14
Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d

View file

@ -3,6 +3,7 @@ Exception in compound assign op should prevent call to overloaded object handler
--FILE--
<?php
#[AllowDynamicProperties]
class Test {
public function __get($k) {
$this->$k = 42;

View file

@ -3,6 +3,7 @@ Test typed properties with integer keys
--FILE--
<?php
#[AllowDynamicProperties]
class T {
// Class must have at least one property. Property must have a type.
// Empty class or untyped property removes segfault

View file

@ -25,6 +25,7 @@
ZEND_API zend_class_entry *zend_ce_attribute;
ZEND_API zend_class_entry *zend_ce_return_type_will_change_attribute;
ZEND_API zend_class_entry *zend_ce_allow_dynamic_properties;
static HashTable internal_attributes;
@ -56,6 +57,18 @@ void validate_attribute(zend_attribute *attr, uint32_t target, zend_class_entry
}
}
static void validate_allow_dynamic_properties(
zend_attribute *attr, uint32_t target, zend_class_entry *scope)
{
if (scope->ce_flags & ZEND_ACC_TRAIT) {
zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to trait");
}
if (scope->ce_flags & ZEND_ACC_INTERFACE) {
zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to interface");
}
scope->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;
}
ZEND_METHOD(Attribute, __construct)
{
zend_long flags = ZEND_ATTRIBUTE_TARGET_ALL;
@ -73,6 +86,11 @@ ZEND_METHOD(ReturnTypeWillChange, __construct)
ZEND_PARSE_PARAMETERS_NONE();
}
ZEND_METHOD(AllowDynamicProperties, __construct)
{
ZEND_PARSE_PARAMETERS_NONE();
}
static zend_attribute *get_attribute(HashTable *attributes, zend_string *lcname, uint32_t offset)
{
if (attributes) {
@ -288,6 +306,10 @@ void zend_register_attribute_ce(void)
zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange();
zend_internal_attribute_register(zend_ce_return_type_will_change_attribute, ZEND_ATTRIBUTE_TARGET_METHOD);
zend_ce_allow_dynamic_properties = register_class_AllowDynamicProperties();
attr = zend_internal_attribute_register(zend_ce_allow_dynamic_properties, ZEND_ATTRIBUTE_TARGET_CLASS);
attr->validator = validate_allow_dynamic_properties;
}
void zend_attributes_shutdown(void)

View file

@ -40,6 +40,7 @@
BEGIN_EXTERN_C()
extern ZEND_API zend_class_entry *zend_ce_attribute;
extern ZEND_API zend_class_entry *zend_ce_allow_dynamic_properties;
typedef struct {
zend_string *name;

View file

@ -13,3 +13,8 @@ final class ReturnTypeWillChange
{
public function __construct() {}
}
final class AllowDynamicProperties
{
public function __construct() {}
}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3fd949e1b9f49666bed3081ed1e8e711acd9f49c */
* Stub hash: 024e849a9dfa8789f13dd1d2ac222a48e4b017f1 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Attribute___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "Attribute::TARGET_ALL")
@ -8,9 +8,12 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReturnTypeWillChange___construct, 0, 0, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_AllowDynamicProperties___construct arginfo_class_ReturnTypeWillChange___construct
ZEND_METHOD(Attribute, __construct);
ZEND_METHOD(ReturnTypeWillChange, __construct);
ZEND_METHOD(AllowDynamicProperties, __construct);
static const zend_function_entry class_Attribute_methods[] = {
@ -24,6 +27,12 @@ static const zend_function_entry class_ReturnTypeWillChange_methods[] = {
ZEND_FE_END
};
static const zend_function_entry class_AllowDynamicProperties_methods[] = {
ZEND_ME(AllowDynamicProperties, __construct, arginfo_class_AllowDynamicProperties___construct, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
static zend_class_entry *register_class_Attribute(void)
{
zend_class_entry ce, *class_entry;
@ -51,3 +60,14 @@ static zend_class_entry *register_class_ReturnTypeWillChange(void)
return class_entry;
}
static zend_class_entry *register_class_AllowDynamicProperties(void)
{
zend_class_entry ce, *class_entry;
INIT_CLASS_ENTRY(ce, "AllowDynamicProperties", class_AllowDynamicProperties_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ZEND_ACC_FINAL;
return class_entry;
}

View file

@ -19,6 +19,7 @@
#include "zend.h"
#include "zend_API.h"
#include "zend_attributes.h"
#include "zend_gc.h"
#include "zend_builtin_functions.h"
#include "zend_constants.h"
@ -33,10 +34,12 @@
/* }}} */
ZEND_MINIT_FUNCTION(core) { /* {{{ */
zend_standard_class_def = register_class_stdClass();
zend_register_default_classes();
zend_standard_class_def = register_class_stdClass();
zend_add_class_attribute(zend_standard_class_def, zend_ce_allow_dynamic_properties->name, 0);
zend_standard_class_def->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;
return SUCCESS;
}
/* }}} */

View file

@ -240,7 +240,7 @@ typedef struct _zend_oparray_context {
/* or IS_CONSTANT_VISITED_MARK | | | */
#define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */
/* | | | */
/* Class Flags (unused: 15,16,21,30,31) | | | */
/* Class Flags (unused: 16,21,30,31) | | | */
/* =========== | | | */
/* | | | */
/* Special class types | | | */
@ -269,6 +269,10 @@ typedef struct _zend_oparray_context {
/* User class has methods with static variables | | | */
#define ZEND_HAS_STATIC_IN_METHODS (1 << 14) /* X | | | */
/* | | | */
/* Objects of this class may have dynamic properties | | | */
/* without triggering a deprecation warning | | | */
#define ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES (1 << 15) /* X | | | */
/* | | | */
/* Parent class is resolved (CE). | | | */
#define ZEND_ACC_RESOLVED_PARENT (1 << 17) /* X | | | */
/* | | | */

View file

@ -1588,7 +1588,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
}
}
ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_USE_GUARDS | ZEND_ACC_NOT_SERIALIZABLE);
ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_USE_GUARDS | ZEND_ACC_NOT_SERIALIZABLE | ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES);
}
/* }}} */

View file

@ -277,6 +277,12 @@ static ZEND_COLD zend_never_inline void zend_forbidden_dynamic_property(
ZSTR_VAL(ce->name), ZSTR_VAL(member));
}
static ZEND_COLD zend_never_inline void zend_deprecated_dynamic_property(
zend_class_entry *ce, zend_string *member) {
zend_error(E_DEPRECATED, "Creation of dynamic property %s::$%s is deprecated",
ZSTR_VAL(ce->name), ZSTR_VAL(member));
}
static ZEND_COLD zend_never_inline void zend_readonly_property_modification_scope_error(
zend_class_entry *ce, zend_string *member, zend_class_entry *scope, const char *operation) {
zend_throw_error(NULL, "Cannot %s readonly property %s::$%s from %s%s",
@ -874,6 +880,9 @@ write_std_property:
variable_ptr = &EG(error_zval);
goto exit;
}
if (UNEXPECTED(!(zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES))) {
zend_deprecated_dynamic_property(zobj->ce, name);
}
Z_TRY_ADDREF_P(value);
if (!zobj->properties) {
@ -1050,6 +1059,9 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam
zend_forbidden_dynamic_property(zobj->ce, name);
return &EG(error_zval);
}
if (UNEXPECTED(!(zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES))) {
zend_deprecated_dynamic_property(zobj->ce, name);
}
if (UNEXPECTED(!zobj->properties)) {
rebuild_object_properties(zobj);
}

View file

@ -2422,7 +2422,7 @@ ZEND_VM_C_LABEL(fast_assign_obj):
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}

View file

@ -22924,7 +22924,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -23055,7 +23055,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -23186,7 +23186,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -23317,7 +23317,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -25482,7 +25482,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -25613,7 +25613,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -25744,7 +25744,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -25875,7 +25875,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -29407,7 +29407,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -29538,7 +29538,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -29669,7 +29669,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -29800,7 +29800,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -31862,7 +31862,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -31993,7 +31993,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -32124,7 +32124,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -32255,7 +32255,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -33724,7 +33724,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -33855,7 +33855,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -33986,7 +33986,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -34117,7 +34117,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -36203,7 +36203,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -36334,7 +36334,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -36465,7 +36465,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -36596,7 +36596,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -40346,7 +40346,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -40477,7 +40477,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -40608,7 +40608,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -40739,7 +40739,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -43986,7 +43986,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -44117,7 +44117,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -44248,7 +44248,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -44379,7 +44379,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -49028,7 +49028,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -49159,7 +49159,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -49290,7 +49290,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}
@ -49421,7 +49421,7 @@ fast_assign_obj:
}
}
if (!zobj->ce->__set) {
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
if (EXPECTED(zobj->properties == NULL)) {
rebuild_object_properties(zobj);
}

View file

@ -37,6 +37,10 @@ object(DateTimeZone)#%d (2) {
}
-- Add some properties --
Deprecated: Creation of dynamic property DateTimeZone::$property1 is deprecated in %s on line %d
Deprecated: Creation of dynamic property DateTimeZone::$property2 is deprecated in %s on line %d
object(DateTimeZone)#%d (4) {
["property1"]=>
int(99)
@ -61,6 +65,10 @@ object(DateTimeZone)#%d (4) {
}
-- Add some more properties --
Deprecated: Creation of dynamic property DateTimeZone::$property3 is deprecated in %s on line %d
Deprecated: Creation of dynamic property DateTimeZone::$property4 is deprecated in %s on line %d
object(DateTimeZone)#%d (6) {
["property1"]=>
int(99)

View file

@ -39,6 +39,10 @@ object(DateTime)#%d (3) {
}
-- Add some properties --
Deprecated: Creation of dynamic property DateTime::$property1 is deprecated in %s on line %d
Deprecated: Creation of dynamic property DateTime::$property2 is deprecated in %s on line %d
object(DateTime)#%d (5) {
["property1"]=>
int(99)
@ -67,6 +71,10 @@ object(DateTime)#%d (5) {
}
-- Add some more properties --
Deprecated: Creation of dynamic property DateTime::$property3 is deprecated in %s on line %d
Deprecated: Creation of dynamic property DateTime::$property4 is deprecated in %s on line %d
object(DateTime)#%d (7) {
["property1"]=>
int(99)

View file

@ -32,7 +32,7 @@ $period->dynamic3[] = "array";
var_dump($period->dynamic3);
?>
--EXPECT--
--EXPECTF--
string(5) "stuff"
string(8) "modified"
array(1) {
@ -40,11 +40,17 @@ array(1) {
string(5) "array"
}
bool(false)
Deprecated: Creation of dynamic property DatePeriod@anonymous::$dynamic1 is deprecated in %s on line %d
string(7) "dynamic"
Deprecated: Creation of dynamic property DatePeriod@anonymous::$dynamic2 is deprecated in %s on line %d
array(1) {
[0]=>
string(5) "array"
}
Deprecated: Creation of dynamic property DatePeriod@anonymous::$dynamic3 is deprecated in %s on line %d
array(1) {
[0]=>
string(5) "array"

View file

@ -6,6 +6,8 @@ date.timezone=UTC
<?php
class Date {
public $date;
public function __construct($in) {
$this->date = date_create($in);
}

View file

@ -12,5 +12,6 @@ while ($i < 1026) {
}
?>
==NOCRASH==
--EXPECT--
--EXPECTF--
Deprecated: Creation of dynamic property Z::$prop is deprecated in %s on line %d
==NOCRASH==

View file

@ -15,6 +15,7 @@ $d->loadXML($xml);
print_r($d);
?>
--EXPECTF--
Deprecated: Creation of dynamic property DOMDocument::$dynamicProperty is deprecated in %s on line %d
DOMDocument Object
(
[config] =>

View file

@ -8,6 +8,7 @@ exif
* Pollute the heap. Helps trigger bug. Sometimes not needed.
*/
class A {
public $a;
function __construct() {
$a = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa';
$this->a = $a . $a . $a . $a . $a . $a;

View file

@ -51,6 +51,8 @@ object(GMP)#%d (1) {
["num"]=>
string(2) "42"
}
Deprecated: Creation of dynamic property GMP::$foo is deprecated in %s on line %d
string(56) "O:3:"GMP":2:{i:0;s:1:"d";i:1;a:1:{s:3:"foo";s:3:"bar";}}"
object(GMP)#%d (2) {
["foo"]=>

View file

@ -15,8 +15,7 @@ setlocale(LC_ALL, "de_DE", "de", "german", "ge", "de_DE.ISO8859-1", "ISO8859-1")
$foo = array(100.10,"bar");
var_dump(json_encode($foo));
class bar {}
$bar1 = new bar;
$bar1 = new stdClass;
$bar1->a = 100.10;
$bar1->b = "foo";
var_dump(json_encode($bar1));

View file

@ -12,10 +12,7 @@ unset ($unset_var);
$fp = fopen(__FILE__, "r");
// get an object
class sample {
}
$obj = new sample();
$obj = new stdClass();
$obj->MyInt = 99;
$obj->MyFloat = 123.45;
$obj->MyBool = true;

View file

@ -2,6 +2,7 @@
json_encode() with JSON_PRETTY_PRINT on declared properties
--FILE--
<?php
#[AllowDynamicProperties]
class MyClass {
public $x;
public $y;
@ -52,4 +53,4 @@ echo json_encode($obj, JSON_PRETTY_PRINT), "\n";
"x": 123
}
{}
{}
{}

View file

@ -14,6 +14,7 @@ open_basedir=.
* Note: Using error_reporting=E_ALL & ~E_NOTICE to suppress "Trying to get property of non-object" notices.
*/
class StreamExploiter {
public $context;
public function stream_close ( ) {
$doc = new DOMDocument;
$doc->resolveExternals = true;

View file

@ -14,6 +14,8 @@ open_basedir=.
* Note: Using error_reporting=E_ALL & ~E_NOTICE to suppress "Trying to get property of non-object" notices.
*/
class StreamExploiter {
public $context;
public function stream_close ( ) {
$doc = new DOMDocument;
$doc->resolveExternals = true;

View file

@ -8,6 +8,8 @@ open_basedir=.
<?php
class StreamExploiter {
public $context;
public function stream_close ( ) {
$doc = new DOMDocument;
$doc->appendChild($doc->createTextNode('hello'));

View file

@ -13,6 +13,7 @@ if (!defined("MYSQLI_ASYNC")) {
<?php
class MySQL_Ext extends mysqli{
protected $fooData = array();
private $extData;
public function isEmpty()
{

View file

@ -24,7 +24,8 @@ require_once('skipifconnectfailure.inc');
}
class mysqli_fetch_object_test {
public $ID;
public $label;
public $a = null;
public $b = null;

View file

@ -19,7 +19,8 @@ require_once('skipifconnectfailure.inc');
}
class mysqli_fetch_object_test {
public $ID;
public $label;
public $a = null;
public $b = null;
@ -51,6 +52,10 @@ require_once('skipifconnectfailure.inc');
--EXPECTF--
No exception with PHP:
object(mysqli_fetch_object_test)#%d (%d) {
["ID"]=>
NULL
["label"]=>
NULL
["a"]=>
NULL
["b"]=>

View file

@ -49,7 +49,8 @@ require_once('skipifconnectfailure.inc');
}
class mysqli_fetch_object_test {
public $ID;
public $label;
public $a = null;
public $b = null;

View file

@ -9,6 +9,7 @@ opcache.jit_buffer_size=1M
opcache
--FILE--
<?php
#[ALlowDynamicProperties]
class C {
var $a = 0;
}

View file

@ -9,6 +9,7 @@ opcache.jit_buffer_size=1M
opcache
--FILE--
<?php
#[AllowDynamicProperties]
class C {
var $a = 0;
}

View file

@ -8,6 +8,7 @@ opcache.jit_buffer_size=1M
opcache.protect_memory=1
--FILE--
<?php
#[AllowDynamicProperties]
class Test {
function foo() {
$this->prop = PHP_INT_MAX - 5;

View file

@ -10,6 +10,7 @@ opcache.preload=
opcache
--FILE--
<?php
#[AllowDynamicProperties]
class A {
}
function foo(int $x) {
@ -21,12 +22,12 @@ function foo(int $x) {
$_main:
; (lines=1, args=0, vars=0, tmps=0)
; (after optimizer)
; %sdce_005.php:1-9
; %s
0000 RETURN int(1)
foo:
; (lines=2, args=1, vars=1, tmps=0)
; (after optimizer)
; %sdce_005.php:4-7
; %s
0000 CV0($x) = RECV 1
0001 RETURN null

View file

@ -29,6 +29,7 @@ class TestBase
private $val2;
}
#[AllowDynamicProperties] // $val2 will be dynamic now.
class TestDerived extends TestBase
{
protected $row;

View file

@ -29,6 +29,9 @@ $stmt = $db->prepare('SELECT classtypes.name, test.id AS id, test.val AS val FRO
class Test1
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";
@ -37,6 +40,9 @@ class Test1
class Test2
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";
@ -45,6 +51,9 @@ class Test2
class Test3
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";

View file

@ -29,6 +29,9 @@ $stmt = $db->prepare('SELECT classtypes.name, test.grp AS grp, test.id AS id, te
class Test1
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";
@ -37,6 +40,9 @@ class Test1
class Test2
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";
@ -45,6 +51,9 @@ class Test2
class Test3
{
public $id;
public $val;
public function __construct()
{
echo __METHOD__ . "()\n";

View file

@ -23,9 +23,8 @@ $db->exec('INSERT INTO test VALUES(4, \'D\', \'Group2\')');
class DerivedStatement extends PDOStatement
{
private function __construct($name, $db)
private function __construct(public $name, $db)
{
$this->name = $name;
echo __METHOD__ . "($name)\n";
}
@ -41,11 +40,9 @@ $derived = $db->prepare('SELECT id, val FROM test', array(PDO::ATTR_STATEMENT_CL
class Test1
{
public function __construct($id, $val)
public function __construct(public $id, public $val)
{
echo __METHOD__ . "($id,$val)\n";
$this->id = $id;
$this->val = $val;
}
static public function factory($id, $val)

View file

@ -26,6 +26,9 @@ var_dump($stmt->fetchAll());
class Test
{
public $val;
public $grp;
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";

View file

@ -32,6 +32,9 @@ foreach ($stmt as $data)
class Test
{
public $val;
public $grp;
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";

View file

@ -22,6 +22,9 @@ $SELECT = 'SELECT val, grp FROM test';
class Test
{
public $val;
public $grp;
function __construct($name = 'N/A')
{
echo __METHOD__ . "($name)\n";

View file

@ -14,6 +14,7 @@ PDOTest::skip();
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
#[AllowDynamicProperties]
class PDOStatementX extends PDOStatement
{
public $test1 = 1;
@ -31,6 +32,7 @@ class PDOStatementX extends PDOStatement
}
}
#[AllowDynamicProperties]
class PDODatabaseX extends PDO
{
public $test1 = 1;

View file

@ -15,6 +15,8 @@ MySQLPDOTest::skip();
class myclass {
public $value;
public function __construct() {
printf("%s()\n", __METHOD__);
}

View file

@ -20,6 +20,7 @@ class PDO3 extends PDO {
class ModelA {
public $db;
public function __construct($h) {
var_dump($h);
if ($h) {

View file

@ -19,6 +19,7 @@ MySQLPDOTest::skip();
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
class HelloWrapper {
public $context;
public function stream_open() { return true; }
public function stream_eof() { return true; }
public function stream_read() { return NULL; }

View file

@ -14,6 +14,7 @@ MySQLPDOTest::skip();
try {
#[AllowDynamicProperties]
class myclass implements Serializable {
private static $instance = null;

View file

@ -30,6 +30,7 @@ try {
$query = "SELECT id, '', NULL, \"\" FROM test ORDER BY id ASC LIMIT 3";
$stmt = $db->prepare($query);
#[AllowDynamicProperties]
class myclass {
private $set_calls = 0;

View file

@ -70,6 +70,8 @@ class PHPUnit_Framework_TestFailure
class PHPUnit_Framework_TestResult
{
private $errors;
public function run( $test)
{
$error = false;

View file

@ -8,6 +8,7 @@ pdo_sqlite
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
#[AllowDynamicProperties]
class Person {
public $test = NULL;
public function __construct() {

View file

@ -14,6 +14,7 @@ $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
class HelloWrapper {
public $context;
public function stream_open() { return true; }
public function stream_eof() { return true; }
public function stream_read() { return NULL; }

Some files were not shown because too many files have changed in this diff Show more