1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.2' into PHP-8.3

This commit is contained in:
Bob Weinand
2023-11-25 01:01:56 +01:00
7 changed files with 160 additions and 2 deletions

4
NEWS
View File

@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.3.1
- Core:
. Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within
ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC). (Florian Engelhardt)
- Standard
. Fixed GH-12745 (http_build_query() default null argument for $arg_separator
is implicitly coerced to string). (Girgias)

View File

@@ -8955,6 +8955,8 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, ANY, REF)
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
SAVE_OPLINE();
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
if (!ht) {
ht = zend_array_dup(EX(func)->op_array.static_variables);
@@ -8964,7 +8966,6 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, ANY, REF)
value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT)));
SAVE_OPLINE();
if (opline->extended_value & ZEND_BIND_REF) {
i_zval_ptr_dtor(variable_ptr);
if (UNEXPECTED(!Z_ISREF_P(value))) {
@@ -9468,6 +9469,7 @@ ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
}
if (result_size) {
SAVE_OPLINE();
uint32_t first_extra_arg = EX(func)->op_array.num_args;
ht = zend_new_array(result_size);

View File

@@ -11037,6 +11037,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE
}
if (result_size) {
SAVE_OPLINE();
uint32_t first_extra_arg = EX(func)->op_array.num_args;
ht = zend_new_array(result_size);
@@ -37143,6 +37144,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS
}
if (result_size) {
SAVE_OPLINE();
uint32_t first_extra_arg = EX(func)->op_array.num_args;
ht = zend_new_array(result_size);
@@ -40498,6 +40500,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_HANDLER(ZE
variable_ptr = EX_VAR(opline->op1.var);
SAVE_OPLINE();
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
if (!ht) {
ht = zend_array_dup(EX(func)->op_array.static_variables);
@@ -40507,7 +40511,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_HANDLER(ZE
value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT)));
SAVE_OPLINE();
if (opline->extended_value & ZEND_BIND_REF) {
i_zval_ptr_dtor(variable_ptr);
if (UNEXPECTED(!Z_ISREF_P(value))) {

View File

@@ -55,6 +55,9 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
int register_passes;
bool print_stderr_mshutdown;
zend_long limit_copy_file_range;
int observe_opline_in_zendmm;
zend_mm_heap* zend_orig_heap;
zend_mm_heap* zend_test_heap;
zend_test_fiber *active_fiber;
zend_long quantity_value;
zend_string *str_test;

View File

@@ -31,10 +31,17 @@
#include "zend_interfaces.h"
#include "zend_weakrefs.h"
#include "Zend/Optimizer/zend_optimizer.h"
#include "Zend/zend_alloc.h"
#include "test_arginfo.h"
#include "zend_call_stack.h"
#include "zend_exceptions.h"
// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from
// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we
// undefine `NDEBUG` and re-include assert.h
#undef NDEBUG
#include "assert.h"
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
# include <libxml/globals.h>
# include <libxml/parser.h>
@@ -622,6 +629,68 @@ static ZEND_FUNCTION(zend_test_crash)
php_printf("%s", invalid);
}
static bool has_opline(zend_execute_data *execute_data)
{
return execute_data
&& execute_data->func
&& ZEND_USER_CODE(execute_data->func->type)
&& execute_data->opline
;
}
void * zend_test_custom_malloc(size_t len)
{
if (has_opline(EG(current_execute_data))) {
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
}
return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
}
void zend_test_custom_free(void *ptr)
{
if (has_opline(EG(current_execute_data))) {
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
}
_zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
}
void * zend_test_custom_realloc(void * ptr, size_t len)
{
if (has_opline(EG(current_execute_data))) {
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
}
return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
}
static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
{
if (new_value == NULL) {
return FAILURE;
}
int int_value = zend_ini_parse_bool(new_value);
if (int_value == 1) {
// `zend_mm_heap` is a private struct, so we have not way to find the
// actual size, but 4096 bytes should be enough
ZT_G(zend_test_heap) = malloc(4096);
memset(ZT_G(zend_test_heap), 0, 4096);
zend_mm_set_custom_handlers(
ZT_G(zend_test_heap),
zend_test_custom_malloc,
zend_test_custom_free,
zend_test_custom_realloc
);
ZT_G(zend_orig_heap) = zend_mm_get_heap();
zend_mm_set_heap(ZT_G(zend_test_heap));
} else if (ZT_G(zend_test_heap)) {
free(ZT_G(zend_test_heap));
ZT_G(zend_test_heap) = NULL;
zend_mm_set_heap(ZT_G(zend_orig_heap));
}
return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
}
static ZEND_FUNCTION(zend_test_fill_packed_array)
{
HashTable *parameter;
@@ -903,6 +972,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_ENTRY("zend_test.not_empty_str_test", "val", PHP_INI_ALL, OnUpdateStrNotEmpty, not_empty_str_test, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.observe_opline_in_zendmm", "0", PHP_INI_ALL, OnUpdateZendTestObserveOplineInZendMM, observe_opline_in_zendmm, zend_zend_test_globals, zend_test_globals)
PHP_INI_END()
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
@@ -1134,6 +1204,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
} ZEND_HASH_FOREACH_END();
zend_hash_destroy(&ZT_G(global_weakmap));
if (ZT_G(zend_test_heap)) {
free(ZT_G(zend_test_heap));
ZT_G(zend_test_heap) = NULL;
zend_mm_set_heap(ZT_G(zend_orig_heap));
}
return SUCCESS;
}

View File

@@ -0,0 +1,33 @@
--TEST--
possible segfault in `ZEND_BIND_STATIC`
--DESCRIPTION--
https://github.com/php/php-src/pull/12758
--EXTENSIONS--
zend_test
--INI--
zend_test.observe_opline_in_zendmm=1
--FILE--
<?php
function &ref() {
static $a = 5;
return $a;
}
class Foo {
public static int $i;
public static string $s = "x";
}
var_dump(Foo::$i = "1");
var_dump(Foo::$s, Foo::$i);
var_dump(ref());
echo 'Done.';
?>
--EXPECT--
int(1)
string(1) "x"
int(1)
int(5)
Done.

View File

@@ -0,0 +1,36 @@
--TEST--
possible segfault in `ZEND_FUNC_GET_ARGS`
--DESCRIPTION--
--EXTENSIONS--
zend_test
--INI--
zend_test.observe_opline_in_zendmm=1
--FILE--
<?php
function ref() {
return func_get_args();
}
class Foo {
public static int $i;
public static string $s = "x";
}
var_dump(Foo::$i = "1");
var_dump(Foo::$s, Foo::$i);
var_dump(ref('string', 0));
echo 'Done.';
?>
--EXPECT--
int(1)
string(1) "x"
int(1)
array(2) {
[0]=>
string(6) "string"
[1]=>
int(0)
}
Done.