summaryrefslogtreecommitdiff
path: root/ext/pcre/php_pcre.c
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2018-12-01 10:24:06 +0100
committerAnatol Belski <ab@php.net>2018-12-01 10:24:06 +0100
commitef1269d5c158afaf052e3d79591462e0f5372b1a (patch)
tree4a7e86e2261e112dde83283bb4ab659644c62fef /ext/pcre/php_pcre.c
parent471eb0dd95e58a5eae7d10b73d2fcb11031cf568 (diff)
downloadphp-git-ef1269d5c158afaf052e3d79591462e0f5372b1a.tar.gz
Fixed bug #77193 Infinite loop in preg_replace_callback
Don't return preallocated match data more than once in nested calls.
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r--ext/pcre/php_pcre.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 5165209b85..ff86458fbf 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -901,17 +901,21 @@ PHPAPI pcre2_code* pcre_get_compiled_regex_ex(zend_string *regex, uint32_t *capt
required, perhaps just a minimum sized data would suffice. */
PHPAPI pcre2_match_data *php_pcre_create_match_data(uint32_t capture_count, pcre2_code *re)
{/*{{{*/
- int rc = 0;
assert(NULL != re);
- if (!capture_count) {
- /* As we deal with a non cached pattern, no other way to gather this info. */
- rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &capture_count);
- }
+ if (EXPECTED(!mdata_used)) {
+ int rc = 0;
+
+ if (!capture_count) {
+ /* As we deal with a non cached pattern, no other way to gather this info. */
+ rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &capture_count);
+ }
- if (rc >= 0 && capture_count + 1 <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
- return mdata;
+ if (rc >= 0 && capture_count + 1 <= PHP_PCRE_PREALLOC_MDATA_SIZE) {
+ mdata_used = 1;
+ return mdata;
+ }
}
return pcre2_match_data_create_from_pattern(re, gctx);
@@ -919,8 +923,10 @@ PHPAPI pcre2_match_data *php_pcre_create_match_data(uint32_t capture_count, pcre
PHPAPI void php_pcre_free_match_data(pcre2_match_data *match_data)
{/*{{{*/
- if (match_data != mdata) {
+ if (UNEXPECTED(match_data != mdata)) {
pcre2_match_data_free(match_data);
+ } else {
+ mdata_used = 0;
}
}/*}}}*/