summaryrefslogtreecommitdiff
path: root/ext/pcre
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-02-10 13:30:25 +0300
committerDmitry Stogov <dmitry@zend.com>2015-02-10 13:30:25 +0300
commit4241a090ada5563c89d9926897b47c0411689816 (patch)
treed127982eff2be339c3c8ad5fa6b1ba8cd4e2b333 /ext/pcre
parent0be776b1fe0b00923378bfb8b9730209265a10d5 (diff)
downloadphp-git-4241a090ada5563c89d9926897b47c0411689816.tar.gz
Avoid reallocation in preg_replace() if nothing was replaced
Diffstat (limited to 'ext/pcre')
-rw-r--r--ext/pcre/php_pcre.c39
-rw-r--r--ext/pcre/php_pcre.h4
2 files changed, 29 insertions, 14 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index c255fd9174..8a6ecb5817 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -998,6 +998,7 @@ static zend_string *preg_do_repl_func(zval *function, char *subject, int *offset
/* {{{ php_pcre_replace
*/
PHPAPI zend_string *php_pcre_replace(zend_string *regex,
+ zend_string *subject_str,
char *subject, int subject_len,
zval *replace_val, int is_callable_replace,
int limit, int *replace_count)
@@ -1009,13 +1010,13 @@ PHPAPI zend_string *php_pcre_replace(zend_string *regex,
return NULL;
}
- return php_pcre_replace_impl(pce, subject, subject_len, replace_val,
+ return php_pcre_replace_impl(pce, subject_str, subject, subject_len, replace_val,
is_callable_replace, limit, replace_count);
}
/* }}} */
/* {{{ php_pcre_replace_impl() */
-PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val,
+PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, int subject_len, zval *replace_val,
int is_callable_replace, int limit, int *replace_count)
{
pcre_extra *extra = pce->extra;/* Holds results of studying */
@@ -1084,8 +1085,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject,
}
}
- alloc_len = 2 * subject_len;
- result = zend_string_alloc(alloc_len * sizeof(char), 0);
+ alloc_len = 0;
+ result = NULL;
/* Initialize */
match = NULL;
@@ -1148,9 +1149,17 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject,
}
}
- if (new_len > alloc_len) {
- alloc_len = alloc_len + 2 * new_len;
- result = zend_string_realloc(result, alloc_len, 0);
+ if (new_len >= alloc_len) {
+ if (alloc_len == 0) {
+ alloc_len = 2 * subject_len;
+ if (new_len >= alloc_len) {
+ alloc_len = alloc_len + 2 * new_len;
+ }
+ result = zend_string_alloc(alloc_len, 0);
+ } else {
+ alloc_len = alloc_len + 2 * new_len;
+ result = zend_string_realloc(result, alloc_len, 0);
+ }
}
/* copy the part of the string before the match */
memcpy(&result->val[result_len], piece, match-piece);
@@ -1205,6 +1214,10 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject,
memcpy(&result->val[result_len], piece, 1);
result_len++;
} else {
+ if (!result && subject_str) {
+ result = zend_string_copy(subject_str);
+ break;
+ }
new_len = result_len + subject_len - start_offset;
if (new_len > alloc_len) {
alloc_len = new_len; /* now we know exactly how long it is */
@@ -1214,12 +1227,15 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject,
memcpy(&result->val[result_len], piece, subject_len - start_offset);
result_len += subject_len - start_offset;
result->val[result_len] = '\0';
+ result->len = result_len;
break;
}
} else {
pcre_handle_exec_error(count);
- zend_string_free(result);
- result = NULL;
+ if (result) {
+ zend_string_free(result);
+ result = NULL;
+ }
break;
}
@@ -1233,9 +1249,6 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject,
start_offset = offsets[1];
}
- if (result) {
- result->len = result_len;
- }
if (size_offsets <= 32) {
free_alloca(offsets, use_heap);
} else {
@@ -1300,6 +1313,7 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
/* Do the actual replacement and put the result back into subject_str
for further replacements. */
if ((result = php_pcre_replace(regex_str,
+ subject_str,
subject_str->val,
(int)subject_str->len,
replace_value,
@@ -1320,6 +1334,7 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
return subject_str;
} else {
result = php_pcre_replace(Z_STR_P(regex),
+ subject_str,
subject_str->val,
(int)subject_str->len,
replace,
diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h
index dc923fe62f..88f810493f 100644
--- a/ext/pcre/php_pcre.h
+++ b/ext/pcre/php_pcre.h
@@ -33,7 +33,7 @@
#include <locale.h>
#endif
-PHPAPI zend_string *php_pcre_replace(zend_string *regex, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count);
+PHPAPI zend_string *php_pcre_replace(zend_string *regex, zend_string *subject_str, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count);
PHPAPI pcre* pcre_get_compiled_regex(zend_string *regex, pcre_extra **extra, int *options);
PHPAPI pcre* pcre_get_compiled_regex_ex(zend_string *regex, pcre_extra **extra, int *preg_options, int *coptions);
@@ -59,7 +59,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex);
PHPAPI void php_pcre_match_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
zval *subpats, int global, int use_flags, zend_long flags, zend_long start_offset);
-PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
+PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, int subject_len, zval *return_value,
int is_callable_replace, int limit, int *replace_count);
PHPAPI void php_pcre_split_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,