diff --git a/NEWS b/NEWS index 527d999a051..6b93d651d10 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ PHP NEWS - PCRE: . Fixed bug #81101 (PCRE2 10.37 shows unexpected result). (Anatol) + . Fixed bug #81243 (Too much memory is allocated for preg_replace()). (cmb) - Standard: . Fixed bug #81223 (flock() only locks first byte of file). (cmb) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 64da43a05f8..19ea9271387 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1719,7 +1719,7 @@ matched: } if (new_len >= alloc_len) { - alloc_len = zend_safe_address_guarded(2, new_len, alloc_len); + alloc_len = zend_safe_address_guarded(2, new_len, 0); if (result == NULL) { result = zend_string_alloc(alloc_len, 0); } else { @@ -1805,14 +1805,12 @@ not_matched: result = zend_string_copy(subject_str); break; } - new_len = result_len + subject_len - last_end_offset; - if (new_len >= alloc_len) { - alloc_len = new_len; /* now we know exactly how long it is */ - if (NULL != result) { - result = zend_string_realloc(result, alloc_len, 0); - } else { - result = zend_string_alloc(alloc_len, 0); - } + /* now we know exactly how long it is */ + alloc_len = result_len + subject_len - last_end_offset; + if (NULL != result) { + result = zend_string_realloc(result, alloc_len, 0); + } else { + result = zend_string_alloc(alloc_len, 0); } /* stick that last bit of string on our output */ memcpy(ZSTR_VAL(result) + result_len, piece, subject_len - last_end_offset); @@ -1959,7 +1957,7 @@ matched: ZEND_ASSERT(eval_result); new_len = zend_safe_address_guarded(1, ZSTR_LEN(eval_result), new_len); if (new_len >= alloc_len) { - alloc_len = zend_safe_address_guarded(2, new_len, alloc_len); + alloc_len = zend_safe_address_guarded(2, new_len, 0); if (result == NULL) { result = zend_string_alloc(alloc_len, 0); } else { @@ -2016,14 +2014,12 @@ not_matched: result = zend_string_copy(subject_str); break; } - new_len = result_len + subject_len - last_end_offset; - if (new_len >= alloc_len) { - alloc_len = new_len; /* now we know exactly how long it is */ - if (NULL != result) { - result = zend_string_realloc(result, alloc_len, 0); - } else { - result = zend_string_alloc(alloc_len, 0); - } + /* now we know exactly how long it is */ + alloc_len = result_len + subject_len - last_end_offset; + if (NULL != result) { + result = zend_string_realloc(result, alloc_len, 0); + } else { + result = zend_string_alloc(alloc_len, 0); } /* stick that last bit of string on our output */ memcpy(ZSTR_VAL(result) + result_len, piece, subject_len - last_end_offset); diff --git a/ext/pcre/tests/bug81243.phpt b/ext/pcre/tests/bug81243.phpt new file mode 100644 index 00000000000..a413f33f6ee --- /dev/null +++ b/ext/pcre/tests/bug81243.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #81243 (Too much memory is allocated for preg_replace()) +--FILE-- + +--EXPECT-- +bool(true) +bool(true)