Skip to content
Merged
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.7.0alpha1

- FPM:
. Use recommended TYPE, HELP order for OpenMetrics metadata.
(Marcel Hernandez)

- Intl:
. Fixed Collator attribute and strength methods not rejecting an
unconstructed Collator. (Ilia Alshanetsky)
Expand Down
5 changes: 4 additions & 1 deletion Zend/Optimizer/zend_call_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ ZEND_API void zend_analyze_calls(zend_arena **arena, zend_script *script, uint32
ALLOCA_FLAG(use_heap);
bool is_prototype;

call_stack = do_alloca((op_array->last / 2) * sizeof(zend_call_info*), use_heap);
// Note: Reserve one call stack slot per operation. Each opcode pushes at
// most one entry to the call stack, and (with dead code elimination) it's
// possible to never pop from the stack.
call_stack = do_alloca(op_array->last * sizeof(zend_call_info*), use_heap);
call_info = NULL;
while (opline != end) {
switch (opline->opcode) {
Expand Down
6 changes: 6 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5324,6 +5324,12 @@ static zend_result zend_compile_func_clone(znode *result, const zend_ast_list *a

static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *args, zend_string *lcname, uint32_t lineno) /* {{{ */
{
/* array_map() as an internal function calls the callback as if strict_types=0,
* this optimization is therefore not legal if strict_types=1. */
if (CG(active_op_array)->fn_flags & ZEND_ACC_STRICT_TYPES) {
return FAILURE;
}

/* Bail out if we do not have exactly two parameters. */
if (args->children != 2) {
return FAILURE;
Expand Down
1 change: 0 additions & 1 deletion ext/dom/html_collection.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ static dom_named_item dom_html_collection_named_item(zend_string *key, zend_obje
xmlNodePtr basep = dom_object_get_node(objmap->baseobj);
if (basep != NULL && basep->children != NULL) {
php_dom_obj_map_collection_iter iter = {0};
iter.candidate = basep->children;
iter.basep = basep;

while (true) {
Expand Down
7 changes: 3 additions & 4 deletions ext/dom/obj_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,7 @@ static void dom_map_get_elements_item(dom_nnodemap_object *map, zend_long index,

static void dom_map_collection_named_item_elements_iter(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter)
{
if (iter->candidate != iter->basep->children) {
iter->candidate = iter->candidate->next;
}
iter->candidate = iter->candidate ? iter->candidate->next : iter->basep->children;
while (iter->candidate && iter->candidate->type != XML_ELEMENT_NODE) {
iter->candidate = iter->candidate->next;
}
Expand Down Expand Up @@ -368,7 +366,8 @@ static void dom_map_get_by_class_name_item(dom_nnodemap_object *map, zend_long i

static void dom_map_collection_named_item_by_tag_name_iter(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter)
{
iter->candidate = dom_get_elements_by_tag_name_ns_raw(iter->basep, iter->candidate, map->ns, map->local, map->local_lower, &iter->cur, iter->next);
xmlNodePtr nodep = iter->candidate ? iter->candidate : iter->basep->children;
iter->candidate = dom_get_elements_by_tag_name_ns_raw(iter->basep, nodep, map->ns, map->local, map->local_lower, &iter->cur, iter->next);
iter->next = iter->cur + 1;
}

Expand Down
39 changes: 39 additions & 0 deletions ext/dom/tests/modern/html/gh23887.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--TEST--
GH-23887 (Dom\HTMLCollection::namedItem() assertion failure, hang, or missed first element)
--CREDITS--
Lu Maltsis (lmaltsis)
--EXTENSIONS--
dom
--FILE--
<?php

$dom = Dom\HTMLDocument::createFromString(<<<HTML
<!DOCTYPE html>
<b id="container">

HTML);
var_dump($dom->getElementById('container')->getElementsByClassName('')->namedItem("here"));

$dom = Dom\HTMLDocument::createFromString('<!DOCTYPE html><div id="c"><p id="a" class="x"></p><p id="b" class="x"></p></div>', LIBXML_NOERROR);
$c = $dom->getElementById('c');

var_dump($c->getElementsByClassName('')->namedItem("a"));
var_dump($c->getElementsByClassName('x')->namedItem("a")->id);
var_dump($c->getElementsByClassName('x')->namedItem("b")->id);
var_dump($c->children->namedItem("a")->id);
var_dump($c->children->namedItem("b")->id);
var_dump($c->children->namedItem("c"));
var_dump($c->getElementsByTagName('p')->namedItem("a")->id);
var_dump($c->getElementsByTagName('p')->namedItem("b")->id);

?>
--EXPECT--
NULL
NULL
string(1) "a"
string(1) "b"
string(1) "a"
string(1) "b"
NULL
string(1) "a"
string(1) "b"
35 changes: 35 additions & 0 deletions ext/opcache/tests/array_map_foreach_optimization_009.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
array_map(): foreach optimization requires strict_types=0 (GH-23882)
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.opt_debug_level=0x20000
--FILE--
<?php

declare(strict_types=1);

var_dump(array_map(trim(...), [1]));

?>
--EXPECTF--
$_main:
; (lines=%d, args=0, vars=%d, tmps=%d)
; (after optimizer)
; %s
0000 INIT_FCALL 1 %d string("var_dump")
0001 INIT_FCALL 2 %d string("array_map")
0002 INIT_FCALL 0 %d string("trim")
0003 T0 = CALLABLE_CONVERT %d
0004 SEND_VAL T0 1
0005 SEND_VAL array(...) 2
0006 T0 = DO_ICALL
0007 SEND_VAL T0 1
0008 DO_ICALL
0009 RETURN int(1)
array(1) {
[0]=>
string(1) "1"
}
17 changes: 17 additions & 0 deletions ext/opcache/tests/opt/call_graph_stack_overflow.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
zend_analyze_calls(): call_stack overflow when dead code elimination removed the DO_FCALLs
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=0x7FFEBFFF
--FILE--
<?php
function test() {
new A(new B(new C(new D(match ([]) { 1 => 2 }))));
}
echo "OK\n";
?>
--EXPECT--
OK
24 changes: 12 additions & 12 deletions sapi/fpm/fpm/fpm_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,44 +380,44 @@ int fpm_status_handle_request(void) /* {{{ */
time_format = "%s";

short_syntax =
"# HELP phpfpm_up Could pool %s using a %s PM on PHP-FPM be reached?\n"
"# TYPE phpfpm_up gauge\n"
"# HELP phpfpm_up Could pool %s using a %s PM on PHP-FPM be reached?\n"
"phpfpm_up 1\n"
"# HELP phpfpm_start_since The number of seconds since FPM has started.\n"
"# TYPE phpfpm_start_since counter\n"
"# HELP phpfpm_start_since The number of seconds since FPM has started.\n"
"phpfpm_start_since %lu\n"
"# HELP phpfpm_accepted_connections The number of requests accepted by the pool.\n"
"# TYPE phpfpm_accepted_connections counter\n"
"# HELP phpfpm_accepted_connections The number of requests accepted by the pool.\n"
"phpfpm_accepted_connections %lu\n"
"# HELP phpfpm_listen_queue The number of requests in the queue of pending connections.\n"
"# TYPE phpfpm_listen_queue gauge\n"
"# HELP phpfpm_listen_queue The number of requests in the queue of pending connections.\n"
"phpfpm_listen_queue %d\n"
"# HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started.\n"
"# TYPE phpfpm_max_listen_queue counter\n"
"# HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started.\n"
"phpfpm_max_listen_queue %d\n"
"# TYPE phpfpm_listen_queue_length gauge\n"
"# HELP phpfpm_listen_queue_length The size of the socket queue of pending connections.\n"
"phpfpm_listen_queue_length %u\n"
"# HELP phpfpm_idle_processes The number of idle processes.\n"
"# TYPE phpfpm_idle_processes gauge\n"
"# HELP phpfpm_idle_processes The number of idle processes.\n"
"phpfpm_idle_processes %d\n"
"# HELP phpfpm_active_processes The number of active processes.\n"
"# TYPE phpfpm_active_processes gauge\n"
"# HELP phpfpm_active_processes The number of active processes.\n"
"phpfpm_active_processes %d\n"
"# HELP phpfpm_total_processes The number of idle + active processes.\n"
"# TYPE phpfpm_total_processes gauge\n"
"# HELP phpfpm_total_processes The number of idle + active processes.\n"
"phpfpm_total_processes %d\n"
"# HELP phpfpm_max_active_processes The maximum number of active processes since FPM has started.\n"
"# TYPE phpfpm_max_active_processes counter\n"
"# HELP phpfpm_max_active_processes The maximum number of active processes since FPM has started.\n"
"phpfpm_max_active_processes %d\n"
"# HELP phpfpm_max_children_reached The number of times, the process limit has been reached, when pm tries to start more children (works only for pm 'dynamic' and 'ondemand').\n"
"# TYPE phpfpm_max_children_reached counter\n"
"# HELP phpfpm_max_children_reached The number of times, the process limit has been reached, when pm tries to start more children (works only for pm 'dynamic' and 'ondemand').\n"
"phpfpm_max_children_reached %u\n"
"# HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value.\n"
"# TYPE phpfpm_slow_requests counter\n"
"# HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value.\n"
"phpfpm_slow_requests %lu\n"
"# HELP phpfpm_memory_peak The memory usage peak since FPM has started.\n"
"# TYPE phpfpm_memory_peak gauge\n"
"# HELP phpfpm_memory_peak The memory usage peak since FPM has started.\n"
"phpfpm_memory_peak %zu\n"
"# EOF\n";

Expand Down
26 changes: 13 additions & 13 deletions sapi/fpm/tests/status.inc
Original file line number Diff line number Diff line change
Expand Up @@ -231,44 +231,44 @@ class Status
*/
protected function checkStatusOpenmetrics(string $body, array $fields)
{
$pattern = "(# HELP phpfpm_up Could pool " . $fields['pool'] . " using a " . $fields['process manager'] . " PM on PHP-FPM be reached\?\n" .
"# TYPE phpfpm_up gauge\n" .
$pattern = "(# TYPE phpfpm_up gauge\n" .
"# HELP phpfpm_up Could pool " . $fields['pool'] . " using a " . $fields['process manager'] . " PM on PHP-FPM be reached\?\n" .
"phpfpm_up 1\n" .
"# HELP phpfpm_start_since The number of seconds since FPM has started\.\n" .
"# TYPE phpfpm_start_since counter\n" .
"# HELP phpfpm_start_since The number of seconds since FPM has started\.\n" .
"phpfpm_start_since " . $fields['start since'] . "\n" .
"# HELP phpfpm_accepted_connections The number of requests accepted by the pool\.\n" .
"# TYPE phpfpm_accepted_connections counter\n" .
"# HELP phpfpm_accepted_connections The number of requests accepted by the pool\.\n" .
"phpfpm_accepted_connections " . $fields['accepted conn'] . "\n" .
"# HELP phpfpm_listen_queue The number of requests in the queue of pending connections\.\n" .
"# TYPE phpfpm_listen_queue gauge\n" .
"# HELP phpfpm_listen_queue The number of requests in the queue of pending connections\.\n" .
"phpfpm_listen_queue " . $fields['listen queue'] . "\n" .
"# HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started\.\n" .
"# TYPE phpfpm_max_listen_queue counter\n" .
"# HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started\.\n" .
"phpfpm_max_listen_queue " . $fields['max listen queue'] . "\n" .
"# TYPE phpfpm_listen_queue_length gauge\n" .
"# HELP phpfpm_listen_queue_length The size of the socket queue of pending connections\.\n" .
"phpfpm_listen_queue_length " . $fields['listen queue len'] . "\n" .
"# HELP phpfpm_idle_processes The number of idle processes\.\n" .
"# TYPE phpfpm_idle_processes gauge\n" .
"# HELP phpfpm_idle_processes The number of idle processes\.\n" .
"phpfpm_idle_processes " . $fields['idle processes'] . "\n" .
"# HELP phpfpm_active_processes The number of active processes\.\n" .
"# TYPE phpfpm_active_processes gauge\n" .
"# HELP phpfpm_active_processes The number of active processes\.\n" .
"phpfpm_active_processes " . $fields['active processes'] . "\n" .
"# HELP phpfpm_total_processes The number of idle \+ active processes\.\n" .
"# TYPE phpfpm_total_processes gauge\n" .
"# HELP phpfpm_total_processes The number of idle \+ active processes\.\n" .
"phpfpm_total_processes " . $fields['total processes'] . "\n" .
"# HELP phpfpm_max_active_processes The maximum number of active processes since FPM has started\.\n" .
"# TYPE phpfpm_max_active_processes counter\n" .
"# HELP phpfpm_max_active_processes The maximum number of active processes since FPM has started\.\n" .
"phpfpm_max_active_processes " . $fields['max active processes'] . "\n" .
"# HELP phpfpm_max_children_reached The number of times, the process limit has been reached, when pm tries to start more children \(works only for pm 'dynamic' and 'ondemand'\)\.\n" .
"# TYPE phpfpm_max_children_reached counter\n" .
"# HELP phpfpm_max_children_reached The number of times, the process limit has been reached, when pm tries to start more children \(works only for pm 'dynamic' and 'ondemand'\)\.\n" .
"phpfpm_max_children_reached " . $fields['max children reached'] . "\n" .
"# HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value\.\n" .
"# TYPE phpfpm_slow_requests counter\n" .
"# HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value\.\n" .
"phpfpm_slow_requests " . $fields['slow requests'] . "\n" .
"# HELP phpfpm_memory_peak The memory usage peak since FPM has started\.\n" .
"# TYPE phpfpm_memory_peak gauge\n" .
"# HELP phpfpm_memory_peak The memory usage peak since FPM has started\.\n" .
"phpfpm_memory_peak " . $fields['memory peak'] . "\n" .
"# EOF)\n";

Expand Down