Skip to content

Commit

Permalink
Fix missing readonly modification error with inc/dec in JIT
Browse files Browse the repository at this point in the history
Closes GH-10746
  • Loading branch information
iluuu1994 committed Mar 2, 2023
1 parent 916b132 commit df93146
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 0 deletions.
2 changes: 2 additions & 0 deletions NEWS
Expand Up @@ -56,6 +56,8 @@ PHP NEWS

- Opcache:
. Fix incorrect page_size check. (nielsdos)
. Fix readonly modification check when using inc/dec operators on readonly
property with JIT. (ilutov)

- OpenSSL:
. Fixed php_openssl_set_server_dh_param() DH params errors handling. (nielsdos)
Expand Down
34 changes: 34 additions & 0 deletions ext/opcache/jit/zend_jit_helpers.c
Expand Up @@ -2655,6 +2655,13 @@ static ZEND_COLD zend_long _zend_jit_throw_dec_prop_error(zend_property_info *pr

static void ZEND_FASTCALL zend_jit_inc_typed_prop(zval *var_ptr, zend_property_info *prop_info)
{
ZEND_ASSERT(Z_TYPE_P(var_ptr) != IS_UNDEF);

if (UNEXPECTED((prop_info->flags & ZEND_ACC_READONLY))) {
zend_readonly_property_modification_error(prop_info);
return;
}

zend_execute_data *execute_data = EG(current_execute_data);
zval tmp;

Expand All @@ -2678,6 +2685,13 @@ static void ZEND_FASTCALL zend_jit_inc_typed_prop(zval *var_ptr, zend_property_i

static void ZEND_FASTCALL zend_jit_dec_typed_prop(zval *var_ptr, zend_property_info *prop_info)
{
ZEND_ASSERT(Z_TYPE_P(var_ptr) != IS_UNDEF);

if (UNEXPECTED((prop_info->flags & ZEND_ACC_READONLY))) {
zend_readonly_property_modification_error(prop_info);
return;
}

zend_execute_data *execute_data = EG(current_execute_data);
zval tmp;

Expand Down Expand Up @@ -2715,6 +2729,16 @@ static void ZEND_FASTCALL zend_jit_pre_dec_typed_prop(zval *var_ptr, zend_proper

static void ZEND_FASTCALL zend_jit_post_inc_typed_prop(zval *var_ptr, zend_property_info *prop_info, zval *result)
{
ZEND_ASSERT(Z_TYPE_P(var_ptr) != IS_UNDEF);

if (UNEXPECTED((prop_info->flags & ZEND_ACC_READONLY))) {
zend_readonly_property_modification_error(prop_info);
if (result) {
ZVAL_UNDEF(result);
}
return;
}

zend_execute_data *execute_data = EG(current_execute_data);

ZVAL_DEREF(var_ptr);
Expand All @@ -2736,6 +2760,16 @@ static void ZEND_FASTCALL zend_jit_post_inc_typed_prop(zval *var_ptr, zend_prope

static void ZEND_FASTCALL zend_jit_post_dec_typed_prop(zval *var_ptr, zend_property_info *prop_info, zval *result)
{
ZEND_ASSERT(Z_TYPE_P(var_ptr) != IS_UNDEF);

if (UNEXPECTED((prop_info->flags & ZEND_ACC_READONLY))) {
zend_readonly_property_modification_error(prop_info);
if (result) {
ZVAL_UNDEF(result);
}
return;
}

zend_execute_data *execute_data = EG(current_execute_data);

ZVAL_DEREF(var_ptr);
Expand Down
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_001.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification post-inc
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
$this->bar++;
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_002.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification pre-inc
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
++$this->bar;
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_003.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification post-inc with result
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
var_dump($this->bar++);
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_004.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification pre-inc with result
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
var_dump(++$this->bar);
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_005.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification post-dec
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
$this->bar--;
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_006.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification pre-dec
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
--$this->bar;
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_007.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification dec-inc with result
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
var_dump($this->bar--);
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d
25 changes: 25 additions & 0 deletions ext/opcache/tests/jit/readonly_008.phpt
@@ -0,0 +1,25 @@
--TEST--
JIT readonly modification pre-dec with result
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=1M
--FILE--
<?php
class Foo {
public readonly int $bar;

public function __construct() {
$this->bar = 1;
var_dump(--$this->bar);
}
}

new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot modify readonly property Foo::$bar in %s:%d
Stack trace:
#0 %s(%d): Foo->__construct()
#1 {main}
thrown in %s on line %d

0 comments on commit df93146

Please sign in to comment.