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
This commit is contained in:
Niels Dossche 2024-10-28 19:33:24 +01:00
commit 91270aafa5
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
7 changed files with 84 additions and 5 deletions

View file

@ -239,8 +239,11 @@ static bool dom_is_pre_insert_valid_without_step_1(php_libxml_ref_obj *document,
ZEND_ASSERT(parentNode != NULL);
/* 1. If parent is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
* => Impossible */
ZEND_ASSERT(!php_dom_pre_insert_is_parent_invalid(parentNode));
* => This is possible because we can grab children of attributes etc... (see e.g. GH-16594) */
if (php_dom_pre_insert_is_parent_invalid(parentNode)) {
php_dom_throw_error(HIERARCHY_REQUEST_ERR, dom_get_strict_error(document));
return false;
}
if (node->doc != documentNode) {
php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(document));

View file

@ -0,0 +1,25 @@
--TEST--
GH-16594 (Assertion failure in DOM -> before)
--EXTENSIONS--
dom
--FILE--
<?php
$v1 = new DOMText("wr");
$v2 = new DOMDocument();
$v6 = new DOMComment("aw");
$v7 = new DOMAttr("r", "iL");
$v9 = $v2->createElement("test");
$v9->setAttributeNodeNS($v7);
$v7->appendChild($v1);
try {
$v1->before($v6);
} catch (DOMException $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Hierarchy Request Error

View file

@ -4464,6 +4464,12 @@ static zend_result accel_preload(const char *config, bool in_child)
/* Release stored values to avoid dangling pointers */
zend_shutdown_executor_values(/* fast_shutdown */ false);
/* On ZTS we execute `executor_globals_ctor` which reset the freelist and p5s pointers, while on NTS we don't.
* We have to clean up the memory before the actual request takes place to avoid a memory leak. */
#ifdef ZTS
zend_shutdown_strtod();
#endif
/* We don't want to preload constants.
* Check that zend_shutdown_executor_values() also destroys constants. */
ZEND_ASSERT(zend_hash_num_elements(EG(zend_constants)) == EG(persistent_constants_count));

View file

@ -10084,6 +10084,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
if ((!func || func->type == ZEND_USER_FUNCTION)
&& opline->opcode != ZEND_DO_ICALL) {
bool recursive_call_through_jmp = 0;
uint32_t num_args = 0;
// JIT: EX(call) = NULL;
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
if (call_num_args <= func->op_array.num_args) {
if (!trace || (trace->op == ZEND_JIT_TRACE_END
&& trace->stop >= ZEND_JIT_TRACE_STOP_INTERPRETER)) {
uint32_t num_args;
if ((func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
if (trace) {
num_args = 0;
@ -10345,7 +10344,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
ir_insn *insn;
/* attempt to convert direct recursive call into loop */
begin = jit->bb_start_ref[call_num_args];
begin = jit->bb_start_ref[num_args];
ZEND_ASSERT(begin != IR_UNUSED);
insn = &jit->ctx.ir_base[begin];
if (insn->op == IR_BEGIN) {

View file

@ -0,0 +1,2 @@
<?php
var_dump(1.5);

View file

@ -0,0 +1,20 @@
--TEST--
GH-16577 (EG(strtod_state).freelist leaks with opcache.preload)
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/gh16577.inc
--EXTENSIONS--
opcache
--SKIPIF--
<?php
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
echo "Done\n";
?>
--EXPECT--
float(1.5)
Done

View file

@ -0,0 +1,24 @@
--TEST--
GH-16572 (Incorrect result with reflection in low-trigger JIT)
--EXTENSIONS--
opcache
--INI--
opcache.jit=1215
--FILE--
<?php
function dumpType(ReflectionType $rt) {
var_dump($rt::class);
dumpType(null);
}
function test1(): int { }
dumpType((new ReflectionFunction('test1'))->getReturnType());
?>
--EXPECTF--
string(19) "ReflectionNamedType"
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
Stack trace:
#0 %s(%d): dumpType(NULL)
#1 %s(%d): dumpType(Object(ReflectionNamedType))
#2 {main}
thrown in %s on line %d