Skip to content

Commit 91270aa

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-16594: Assertion failure in DOM -> before Fix GH-16572: Incorrect result with reflection in low-trigger JIT Fix GH-16577: EG(strtod_state).freelist leaks with opcache.preload
2 parents 562677a + 947e319 commit 91270aa

File tree

7 files changed

+84
-5
lines changed

7 files changed

+84
-5
lines changed

ext/dom/parentnode/tree.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,11 @@ static bool dom_is_pre_insert_valid_without_step_1(php_libxml_ref_obj *document,
239239
ZEND_ASSERT(parentNode != NULL);
240240

241241
/* 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
242-
* => Impossible */
243-
ZEND_ASSERT(!php_dom_pre_insert_is_parent_invalid(parentNode));
242+
* => This is possible because we can grab children of attributes etc... (see e.g. GH-16594) */
243+
if (php_dom_pre_insert_is_parent_invalid(parentNode)) {
244+
php_dom_throw_error(HIERARCHY_REQUEST_ERR, dom_get_strict_error(document));
245+
return false;
246+
}
244247

245248
if (node->doc != documentNode) {
246249
php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(document));

ext/dom/tests/gh16594.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-16594 (Assertion failure in DOM -> before)
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$v1 = new DOMText("wr");
9+
$v2 = new DOMDocument();
10+
$v6 = new DOMComment("aw");
11+
$v7 = new DOMAttr("r", "iL");
12+
13+
$v9 = $v2->createElement("test");
14+
$v9->setAttributeNodeNS($v7);
15+
$v7->appendChild($v1);
16+
17+
try {
18+
$v1->before($v6);
19+
} catch (DOMException $e) {
20+
echo $e->getMessage(), "\n";
21+
}
22+
23+
?>
24+
--EXPECT--
25+
Hierarchy Request Error

ext/opcache/ZendAccelerator.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4464,6 +4464,12 @@ static zend_result accel_preload(const char *config, bool in_child)
44644464
/* Release stored values to avoid dangling pointers */
44654465
zend_shutdown_executor_values(/* fast_shutdown */ false);
44664466

4467+
/* On ZTS we execute `executor_globals_ctor` which reset the freelist and p5s pointers, while on NTS we don't.
4468+
* We have to clean up the memory before the actual request takes place to avoid a memory leak. */
4469+
#ifdef ZTS
4470+
zend_shutdown_strtod();
4471+
#endif
4472+
44674473
/* We don't want to preload constants.
44684474
* Check that zend_shutdown_executor_values() also destroys constants. */
44694475
ZEND_ASSERT(zend_hash_num_elements(EG(zend_constants)) == EG(persistent_constants_count));

ext/opcache/jit/zend_jit_ir.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10084,6 +10084,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1008410084
if ((!func || func->type == ZEND_USER_FUNCTION)
1008510085
&& opline->opcode != ZEND_DO_ICALL) {
1008610086
bool recursive_call_through_jmp = 0;
10087+
uint32_t num_args = 0;
1008710088

1008810089
// JIT: EX(call) = NULL;
1008910090
ir_STORE(jit_CALL(rx, call), IR_NULL);
@@ -10148,8 +10149,6 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1014810149
if (call_num_args <= func->op_array.num_args) {
1014910150
if (!trace || (trace->op == ZEND_JIT_TRACE_END
1015010151
&& trace->stop >= ZEND_JIT_TRACE_STOP_INTERPRETER)) {
10151-
uint32_t num_args;
10152-
1015310152
if ((func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
1015410153
if (trace) {
1015510154
num_args = 0;
@@ -10345,7 +10344,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1034510344
ir_insn *insn;
1034610345

1034710346
/* attempt to convert direct recursive call into loop */
10348-
begin = jit->bb_start_ref[call_num_args];
10347+
begin = jit->bb_start_ref[num_args];
1034910348
ZEND_ASSERT(begin != IR_UNUSED);
1035010349
insn = &jit->ctx.ir_base[begin];
1035110350
if (insn->op == IR_BEGIN) {

ext/opcache/tests/gh16577.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
var_dump(1.5);

ext/opcache/tests/gh16577.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-16577 (EG(strtod_state).freelist leaks with opcache.preload)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/gh16577.inc
8+
--EXTENSIONS--
9+
opcache
10+
--SKIPIF--
11+
<?php
12+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
13+
?>
14+
--FILE--
15+
<?php
16+
echo "Done\n";
17+
?>
18+
--EXPECT--
19+
float(1.5)
20+
Done

ext/opcache/tests/jit/gh16572.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GH-16572 (Incorrect result with reflection in low-trigger JIT)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit=1215
7+
--FILE--
8+
<?php
9+
function dumpType(ReflectionType $rt) {
10+
var_dump($rt::class);
11+
dumpType(null);
12+
}
13+
function test1(): int { }
14+
dumpType((new ReflectionFunction('test1'))->getReturnType());
15+
?>
16+
--EXPECTF--
17+
string(19) "ReflectionNamedType"
18+
19+
Fatal error: Uncaught TypeError: dumpType(): Argument #1 ($rt) must be of type ReflectionType, null given, called in %s on line %d and defined in %s:%d
20+
Stack trace:
21+
#0 %s(%d): dumpType(NULL)
22+
#1 %s(%d): dumpType(Object(ReflectionNamedType))
23+
#2 {main}
24+
thrown in %s on line %d

0 commit comments

Comments
 (0)