mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.2'
* PHP-8.2: Revert "Fix GH-10168: heap-buffer-overflow at zval_undefined_cv"
This commit is contained in:
commit
a3e44bbb9d
7 changed files with 210 additions and 502 deletions
|
@ -1,32 +0,0 @@
|
||||||
--TEST--
|
|
||||||
GH-10168 (heap-buffer-overflow at zval_undefined_cv): array variation
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
static $instances;
|
|
||||||
public function __construct() {
|
|
||||||
(self::$instances[NULL] = $this) > 0;
|
|
||||||
var_dump(self::$instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
function __destruct() {
|
|
||||||
unset(self::$instances[NULL]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new Test();
|
|
||||||
new Test();
|
|
||||||
|
|
||||||
?>
|
|
||||||
--EXPECTF--
|
|
||||||
Notice: Object of class Test could not be converted to int in %s on line %d
|
|
||||||
array(1) {
|
|
||||||
[""]=>
|
|
||||||
object(Test)#1 (0) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Notice: Object of class Test could not be converted to int in %s on line %d
|
|
||||||
array(0) {
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
--TEST--
|
|
||||||
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign global variation
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$a = null;
|
|
||||||
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
public function __construct() {
|
|
||||||
($GLOBALS['a'] = $this) > 0;
|
|
||||||
// Destructor called after comparison, so a will be NULL
|
|
||||||
var_dump($GLOBALS['a']);
|
|
||||||
}
|
|
||||||
|
|
||||||
function __destruct() {
|
|
||||||
unset($GLOBALS['a']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new Test();
|
|
||||||
new Test();
|
|
||||||
|
|
||||||
?>
|
|
||||||
--EXPECTF--
|
|
||||||
Notice: Object of class Test could not be converted to int in %s on line %d
|
|
||||||
object(Test)#1 (0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Notice: Object of class Test could not be converted to int in %s on line %d
|
|
||||||
|
|
||||||
Warning: Undefined global variable $a in %s on line %d
|
|
||||||
NULL
|
|
|
@ -1,30 +0,0 @@
|
||||||
--TEST--
|
|
||||||
GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop
|
|
||||||
--XFAIL--
|
|
||||||
--FILE--
|
|
||||||
<?php
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
static ?Test $a = null;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
if (self::$a === null) {
|
|
||||||
var_dump(self::$a = &$this);
|
|
||||||
} else {
|
|
||||||
var_dump(self::$a = $this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function __destruct() {
|
|
||||||
self::$a = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new Test();
|
|
||||||
new Test();
|
|
||||||
|
|
||||||
?>
|
|
||||||
--EXPECTF--
|
|
||||||
object(Test)#1 (0) {
|
|
||||||
}
|
|
||||||
object(Test)#2 (0) {
|
|
||||||
}
|
|
|
@ -3587,7 +3587,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr)
|
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
zval value;
|
zval value;
|
||||||
|
@ -3607,9 +3607,6 @@ ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *ori
|
||||||
} else {
|
} else {
|
||||||
zval_ptr_dtor_nogc(&value);
|
zval_ptr_dtor_nogc(&value);
|
||||||
}
|
}
|
||||||
if (result_variable_ptr) {
|
|
||||||
ZVAL_COPY(result_variable_ptr, variable_ptr);
|
|
||||||
}
|
|
||||||
if (value_type & (IS_VAR|IS_TMP_VAR)) {
|
if (value_type & (IS_VAR|IS_TMP_VAR)) {
|
||||||
if (UNEXPECTED(ref)) {
|
if (UNEXPECTED(ref)) {
|
||||||
if (UNEXPECTED(GC_DELREF(ref) == 0)) {
|
if (UNEXPECTED(GC_DELREF(ref) == 0)) {
|
||||||
|
@ -3623,11 +3620,6 @@ ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *ori
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict)
|
|
||||||
{
|
|
||||||
return zend_assign_to_typed_ref_and_result(variable_ptr, orig_value, value_type, strict, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(const zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context) {
|
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(const zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context) {
|
||||||
zval *val = orig_val;
|
zval *val = orig_val;
|
||||||
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
||||||
|
|
|
@ -118,7 +118,6 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret);
|
||||||
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop);
|
||||||
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop);
|
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop);
|
||||||
|
|
||||||
ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr);
|
|
||||||
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict);
|
ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict);
|
||||||
|
|
||||||
static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type)
|
static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type)
|
||||||
|
@ -148,22 +147,12 @@ static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_always_inline void zend_handle_garbage_from_variable_assignment(zend_refcounted *garbage)
|
|
||||||
{
|
|
||||||
if (GC_DELREF(garbage) == 0) {
|
|
||||||
rc_dtor_func(garbage);
|
|
||||||
} else { /* we need to split */
|
|
||||||
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
|
||||||
if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
|
|
||||||
gc_possible_root(garbage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict)
|
static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
||||||
|
zend_refcounted *garbage;
|
||||||
|
|
||||||
if (Z_ISREF_P(variable_ptr)) {
|
if (Z_ISREF_P(variable_ptr)) {
|
||||||
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
|
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
|
||||||
return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict);
|
return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict);
|
||||||
|
@ -174,42 +163,21 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
|
garbage = Z_COUNTED_P(variable_ptr);
|
||||||
zend_copy_to_variable(variable_ptr, value, value_type);
|
zend_copy_to_variable(variable_ptr, value, value_type);
|
||||||
zend_handle_garbage_from_variable_assignment(garbage);
|
if (GC_DELREF(garbage) == 0) {
|
||||||
return variable_ptr;
|
rc_dtor_func(garbage);
|
||||||
}
|
} else { /* we need to split */
|
||||||
} while (0);
|
/* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */
|
||||||
|
if (UNEXPECTED(GC_MAY_LEAK(garbage))) {
|
||||||
zend_copy_to_variable(variable_ptr, value, value_type);
|
gc_possible_root(garbage);
|
||||||
return variable_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static zend_always_inline zval* zend_assign_to_two_variables(zval *result_variable_ptr, zval *variable_ptr, zval *value, zend_uchar value_type, bool strict)
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
|
|
||||||
if (Z_ISREF_P(variable_ptr)) {
|
|
||||||
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) {
|
|
||||||
variable_ptr = zend_assign_to_typed_ref_and_result(variable_ptr, value, value_type, strict, result_variable_ptr);
|
|
||||||
return variable_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
variable_ptr = Z_REFVAL_P(variable_ptr);
|
|
||||||
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
|
|
||||||
zend_copy_to_variable(variable_ptr, value, value_type);
|
|
||||||
ZVAL_COPY(result_variable_ptr, variable_ptr);
|
|
||||||
zend_handle_garbage_from_variable_assignment(garbage);
|
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
zend_copy_to_variable(variable_ptr, value, value_type);
|
zend_copy_to_variable(variable_ptr, value, value_type);
|
||||||
ZVAL_COPY(result_variable_ptr, variable_ptr);
|
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2587,9 +2587,6 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
|
||||||
Z_ADDREF_P(value);
|
Z_ADDREF_P(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
||||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
|
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||||
if (OP2_TYPE == IS_CONST) {
|
if (OP2_TYPE == IS_CONST) {
|
||||||
|
@ -2601,11 +2598,10 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
|
||||||
ZEND_VM_C_GOTO(assign_dim_error);
|
ZEND_VM_C_GOTO(assign_dim_error);
|
||||||
}
|
}
|
||||||
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
|
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
|
||||||
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES());
|
||||||
zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES());
|
}
|
||||||
} else {
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||||
zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES());
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
||||||
|
@ -2699,14 +2695,12 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
|
||||||
value = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
value = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||||
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
|
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
|
||||||
|
|
||||||
if (RETURN_VALUE_USED(opline)) {
|
value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES());
|
||||||
zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES());
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
||||||
} else {
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||||
zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_OP1();
|
FREE_OP1();
|
||||||
/* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
||||||
|
|
||||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||||
}
|
}
|
||||||
|
|
536
Zend/zend_vm_execute.h
generated
536
Zend/zend_vm_execute.h
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue