diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 6a24691a170e..dfff4640be2d 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -2316,6 +2316,16 @@ static void _preg_replace_common( RETURN_THROWS(); } + if (regex_ht) { + GC_TRY_ADDREF(regex_ht); + } + if (replace_ht) { + GC_TRY_ADDREF(replace_ht); + } + if (subject_ht) { + GC_TRY_ADDREF(subject_ht); + } + if (subject_str) { old_replace_count = replace_count; result = php_replace_in_subject(regex_str, regex_ht, replace_str, replace_ht, @@ -2370,6 +2380,16 @@ static void _preg_replace_common( if (zcount) { ZEND_TRY_ASSIGN_REF_LONG(zcount, replace_count); } + + if (regex_ht) { + GC_TRY_DTOR_NO_REF(regex_ht); + } + if (replace_ht) { + GC_TRY_DTOR_NO_REF(replace_ht); + } + if (subject_ht) { + GC_TRY_DTOR_NO_REF(subject_ht); + } } /* {{{ preg_replace_common */ diff --git a/ext/pcre/tests/gh23204.phpt b/ext/pcre/tests/gh23204.phpt new file mode 100644 index 000000000000..9f56d3bd6f17 --- /dev/null +++ b/ext/pcre/tests/gh23204.phpt @@ -0,0 +1,78 @@ +--TEST-- +GH-23204 (Use-after-free when __toString() destroys the array being read) +--FILE-- +getMessage(), PHP_EOL; +} +?> +--EXPECT-- +string(4) "zzzz" +NULL +string(4) "zyyy" +array(2) { + [0]=> + string(4) "zbcd" + [1]=> + string(4) "zbcd" +} +string(3) "XXz" +int(3) +Exception: boom