From 405bf027c9470fec580966d0b7da894d406c0203 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 12 May 2026 17:40:10 -0400 Subject: [PATCH] ext/pcre: fix duplicate MARK key in matches array When a named capture group is also called "MARK" and the pattern uses the (*MARK:name) directive, populate_subpat_array() inserted two buckets with the same string key into the matches array. zend_hash_str_add_new skips the duplicate-key check, so the named capture's MARK and the directive's MARK both landed in the table. Switch to zend_hash_str_update so the directive's value overwrites the capture's value, restoring the behavior that existed via add_assoc_string_ex before d6cc31cf9538. --- ext/pcre/php_pcre.c | 2 +- ext/pcre/tests/mark_named_collision.phpt | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 ext/pcre/tests/mark_named_collision.phpt diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index b9f8e1211ff5..6a62d9717e7b 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1079,7 +1079,7 @@ static void populate_subpat_array( /* Add MARK, if available */ if (mark) { ZVAL_STRING(&val, (char *)mark); - zend_hash_str_add_new(subpats_ht, ZEND_STRL("MARK"), &val); + zend_hash_str_update(subpats_ht, ZEND_STRL("MARK"), &val); } } diff --git a/ext/pcre/tests/mark_named_collision.phpt b/ext/pcre/tests/mark_named_collision.phpt new file mode 100644 index 000000000000..b644c4d44023 --- /dev/null +++ b/ext/pcre/tests/mark_named_collision.phpt @@ -0,0 +1,15 @@ +--TEST-- +preg_match: (*MARK:name) directive does not collide with named group called MARK +--FILE-- +[abc])(*MARK:value)/', "abc", $m); +echo "count: ", count($m), "\n"; +echo "MARK: ", $m['MARK'], "\n"; +echo "json: ", json_encode($m), "\n"; +echo "keys: ", implode(',', array_keys($m)), "\n"; +?> +--EXPECT-- +count: 3 +MARK: value +json: {"0":"a","MARK":"value","1":"a"} +keys: 0,MARK,1