Skip to content

Commit 50ccea3

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
2 parents 73246ba + 1305ea2 commit 50ccea3

File tree

7 files changed

+158
-2
lines changed

7 files changed

+158
-2
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ PHP NEWS
77
error handler). (ilutov)
88
. Fixed oss-fuzz #64209 (In-place modification of filename in
99
php_message_handler_for_zend). (ilutov)
10+
. Fixed bug GH-12758 / GH-12768 (Invalid opline in OOM handlers within
11+
ZEND_FUNC_GET_ARGS and ZEND_BIND_STATIC). (Florian Engelhardt)
1012

1113
- Date:
1214
. Fixed improbably integer overflow while parsing really large (or small)

Zend/zend_vm_def.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -8851,6 +8851,8 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
88518851

88528852
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
88538853

8854+
SAVE_OPLINE();
8855+
88548856
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
88558857
if (!ht) {
88568858
ht = zend_array_dup(EX(func)->op_array.static_variables);
@@ -8860,7 +8862,6 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
88608862

88618863
value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT)));
88628864

8863-
SAVE_OPLINE();
88648865
if (opline->extended_value & ZEND_BIND_REF) {
88658866
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
88668867
if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) {
@@ -9314,6 +9315,7 @@ ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
93149315
}
93159316

93169317
if (result_size) {
9318+
SAVE_OPLINE();
93179319
uint32_t first_extra_arg = EX(func)->op_array.num_args;
93189320

93199321
ht = zend_new_array(result_size);

Zend/zend_vm_execute.h

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/zend_test/php_test.h

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
5555
int register_passes;
5656
bool print_stderr_mshutdown;
5757
zend_long limit_copy_file_range;
58+
int observe_opline_in_zendmm;
59+
zend_mm_heap* zend_orig_heap;
60+
zend_mm_heap* zend_test_heap;
5861
zend_test_fiber *active_fiber;
5962
zend_long quantity_value;
6063
zend_string *str_test;

ext/zend_test/test.c

+77
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@
3030
#include "zend_interfaces.h"
3131
#include "zend_weakrefs.h"
3232
#include "Zend/Optimizer/zend_optimizer.h"
33+
#include "Zend/zend_alloc.h"
3334
#include "test.h"
3435
#include "test_arginfo.h"
3536

37+
// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from
38+
// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we
39+
// undefine `NDEBUG` and re-include assert.h
40+
#undef NDEBUG
41+
#include "assert.h"
42+
3643
#if defined(HAVE_LIBXML) && !defined(PHP_WIN32)
3744
# include <libxml/globals.h>
3845
# include <libxml/parser.h>
@@ -501,6 +508,68 @@ static ZEND_FUNCTION(zend_test_crash)
501508
php_printf("%s", invalid);
502509
}
503510

511+
static bool has_opline(zend_execute_data *execute_data)
512+
{
513+
return execute_data
514+
&& execute_data->func
515+
&& ZEND_USER_CODE(execute_data->func->type)
516+
&& execute_data->opline
517+
;
518+
}
519+
520+
void * zend_test_custom_malloc(size_t len)
521+
{
522+
if (has_opline(EG(current_execute_data))) {
523+
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
524+
}
525+
return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
526+
}
527+
528+
void zend_test_custom_free(void *ptr)
529+
{
530+
if (has_opline(EG(current_execute_data))) {
531+
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
532+
}
533+
_zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
534+
}
535+
536+
void * zend_test_custom_realloc(void * ptr, size_t len)
537+
{
538+
if (has_opline(EG(current_execute_data))) {
539+
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
540+
}
541+
return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
542+
}
543+
544+
static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
545+
{
546+
if (new_value == NULL) {
547+
return FAILURE;
548+
}
549+
550+
int int_value = zend_ini_parse_bool(new_value);
551+
552+
if (int_value == 1) {
553+
// `zend_mm_heap` is a private struct, so we have not way to find the
554+
// actual size, but 4096 bytes should be enough
555+
ZT_G(zend_test_heap) = malloc(4096);
556+
memset(ZT_G(zend_test_heap), 0, 4096);
557+
zend_mm_set_custom_handlers(
558+
ZT_G(zend_test_heap),
559+
zend_test_custom_malloc,
560+
zend_test_custom_free,
561+
zend_test_custom_realloc
562+
);
563+
ZT_G(zend_orig_heap) = zend_mm_get_heap();
564+
zend_mm_set_heap(ZT_G(zend_test_heap));
565+
} else if (ZT_G(zend_test_heap)) {
566+
free(ZT_G(zend_test_heap));
567+
ZT_G(zend_test_heap) = NULL;
568+
zend_mm_set_heap(ZT_G(zend_orig_heap));
569+
}
570+
return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
571+
}
572+
504573
static ZEND_FUNCTION(zend_test_is_pcre_bundled)
505574
{
506575
ZEND_PARSE_PARAMETERS_NONE();
@@ -743,6 +812,7 @@ PHP_INI_BEGIN()
743812
STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
744813
STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
745814
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)
815+
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)
746816
PHP_INI_END()
747817

748818
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
@@ -899,6 +969,13 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
899969
zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
900970
} ZEND_HASH_FOREACH_END();
901971
zend_hash_destroy(&ZT_G(global_weakmap));
972+
973+
if (ZT_G(zend_test_heap)) {
974+
free(ZT_G(zend_test_heap));
975+
ZT_G(zend_test_heap) = NULL;
976+
zend_mm_set_heap(ZT_G(zend_orig_heap));
977+
}
978+
902979
return SUCCESS;
903980
}
904981

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
possible segfault in `ZEND_BIND_STATIC`
3+
--DESCRIPTION--
4+
https://github.com/php/php-src/pull/12758
5+
--EXTENSIONS--
6+
zend_test
7+
--INI--
8+
zend_test.observe_opline_in_zendmm=1
9+
--FILE--
10+
<?php
11+
12+
function &ref() {
13+
static $a = 5;
14+
return $a;
15+
}
16+
17+
class Foo {
18+
public static int $i;
19+
public static string $s = "x";
20+
}
21+
22+
var_dump(Foo::$i = "1");
23+
var_dump(Foo::$s, Foo::$i);
24+
var_dump(ref());
25+
26+
echo 'Done.';
27+
?>
28+
--EXPECT--
29+
int(1)
30+
string(1) "x"
31+
int(1)
32+
int(5)
33+
Done.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
possible segfault in `ZEND_FUNC_GET_ARGS`
3+
--DESCRIPTION--
4+
--EXTENSIONS--
5+
zend_test
6+
--INI--
7+
zend_test.observe_opline_in_zendmm=1
8+
--FILE--
9+
<?php
10+
11+
function ref() {
12+
return func_get_args();
13+
}
14+
15+
class Foo {
16+
public static int $i;
17+
public static string $s = "x";
18+
}
19+
20+
var_dump(Foo::$i = "1");
21+
var_dump(Foo::$s, Foo::$i);
22+
var_dump(ref('string', 0));
23+
24+
echo 'Done.';
25+
?>
26+
--EXPECT--
27+
int(1)
28+
string(1) "x"
29+
int(1)
30+
array(2) {
31+
[0]=>
32+
string(6) "string"
33+
[1]=>
34+
int(0)
35+
}
36+
Done.

0 commit comments

Comments
 (0)