diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-02-10 13:30:25 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-02-10 13:30:25 +0300 |
commit | 4241a090ada5563c89d9926897b47c0411689816 (patch) | |
tree | d127982eff2be339c3c8ad5fa6b1ba8cd4e2b333 | |
parent | 0be776b1fe0b00923378bfb8b9730209265a10d5 (diff) | |
download | php-git-4241a090ada5563c89d9926897b47c0411689816.tar.gz |
Avoid reallocation in preg_replace() if nothing was replaced
-rw-r--r-- | ext/fileinfo/libmagic/funcs.c | 2 | ||||
-rw-r--r-- | ext/pcre/php_pcre.c | 39 | ||||
-rw-r--r-- | ext/pcre/php_pcre.h | 4 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 54 | ||||
-rw-r--r-- | win32/sendmail.c | 15 |
5 files changed, 58 insertions, 56 deletions
diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c index 4df0a2a496..82f4cd38cd 100644 --- a/ext/fileinfo/libmagic/funcs.c +++ b/ext/fileinfo/libmagic/funcs.c @@ -457,7 +457,7 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep) zval_ptr_dtor(&patt); ZVAL_STRING(&repl, rep); - res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), &repl, 0, -1, &rep_cnt); + res = php_pcre_replace_impl(pce, NULL, ms->o.buf, strlen(ms->o.buf), &repl, 0, -1, &rep_cnt); zval_ptr_dtor(&repl); if (NULL == res) { 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, diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index bb7424a395..21b3c8c905 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2028,10 +2028,9 @@ SPL_METHOD(CallbackFilterIterator, accept) SPL_METHOD(RegexIterator, accept) { spl_dual_it_object *intern; - char *subject; - zend_string *result; - int subject_len, use_copy, count = 0; - zval *subject_ptr, subject_copy, zcount, *replacement, tmp_replacement, rv; + zend_string *result, *subject; + int count = 0; + zval zcount, *replacement, tmp_replacement, rv; if (zend_parse_parameters_none() == FAILURE) { return; @@ -2046,51 +2045,40 @@ SPL_METHOD(RegexIterator, accept) } if (intern->u.regex.flags & REGIT_USE_KEY) { - subject_ptr = &intern->current.key; + subject = zval_get_string(&intern->current.key); } else { - subject_ptr = &intern->current.data; + subject = zval_get_string(&intern->current.data); } - ZVAL_UNDEF(&subject_copy); - use_copy = zend_make_printable_zval(subject_ptr, &subject_copy); - if (use_copy) { - subject = Z_STRVAL(subject_copy); - subject_len = (int)Z_STRLEN(subject_copy); - } else { - subject = Z_STRVAL_P(subject_ptr); - subject_len = (int)Z_STRLEN_P(subject_ptr); - } - - use_copy = 0; switch (intern->u.regex.mode) { case REGIT_MODE_MAX: /* won't happen but makes compiler happy */ case REGIT_MODE_MATCH: - count = pcre_exec(intern->u.regex.pce->re, intern->u.regex.pce->extra, subject, subject_len, 0, 0, NULL, 0); + count = pcre_exec(intern->u.regex.pce->re, intern->u.regex.pce->extra, subject->val, subject->len, 0, 0, NULL, 0); RETVAL_BOOL(count >= 0); break; case REGIT_MODE_ALL_MATCHES: case REGIT_MODE_GET_MATCH: - if (!use_copy) { - subject = estrndup(subject, subject_len); - use_copy = 1; - } +//??? if (!use_copy) { +//??? subject = estrndup(subject, subject_len); +//??? use_copy = 1; +//??? } zval_ptr_dtor(&intern->current.data); ZVAL_UNDEF(&intern->current.data); - php_pcre_match_impl(intern->u.regex.pce, subject, subject_len, &zcount, + php_pcre_match_impl(intern->u.regex.pce, subject->val, subject->len, &zcount, &intern->current.data, intern->u.regex.mode == REGIT_MODE_ALL_MATCHES, intern->u.regex.use_flags, intern->u.regex.preg_flags, 0); RETVAL_BOOL(Z_LVAL(zcount) > 0); break; case REGIT_MODE_SPLIT: - if (!use_copy) { - subject = estrndup(subject, subject_len); - use_copy = 1; - } +//??? if (!use_copy) { +//??? subject = estrndup(subject, subject_len); +//??? use_copy = 1; +//??? } zval_ptr_dtor(&intern->current.data); ZVAL_UNDEF(&intern->current.data); - php_pcre_split_impl(intern->u.regex.pce, subject, subject_len, &intern->current.data, -1, intern->u.regex.preg_flags); + php_pcre_split_impl(intern->u.regex.pce, subject->val, subject->len, &intern->current.data, -1, intern->u.regex.preg_flags); count = zend_hash_num_elements(Z_ARRVAL(intern->current.data)); RETVAL_BOOL(count > 1); break; @@ -2103,7 +2091,7 @@ SPL_METHOD(RegexIterator, accept) convert_to_string(&tmp_replacement); replacement = &tmp_replacement; } - result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject_len, replacement, 0, -1, &count); + result = php_pcre_replace_impl(intern->u.regex.pce, subject, subject->val, subject->len, replacement, 0, -1, &count); if (intern->u.regex.flags & REGIT_USE_KEY) { zval_ptr_dtor(&intern->current.key); @@ -2122,13 +2110,7 @@ SPL_METHOD(RegexIterator, accept) if (intern->u.regex.flags & REGIT_INVERTED) { RETVAL_BOOL(Z_TYPE_P(return_value) != IS_TRUE); } - - if (use_copy) { - efree(subject); - } - if (!Z_ISUNDEF(subject_copy)) { - zval_ptr_dtor(&subject_copy); - } + zend_string_release(subject); } /* }}} */ /* {{{ proto string RegexIterator::getRegex() diff --git a/win32/sendmail.c b/win32/sendmail.c index 0254d82ee9..fd7424dda7 100644 --- a/win32/sendmail.c +++ b/win32/sendmail.c @@ -168,15 +168,16 @@ static zend_string *php_win32_mail_trim_header(char *header) regex = zend_string_init(PHP_WIN32_MAIL_UNIFY_PATTERN, sizeof(PHP_WIN32_MAIL_UNIFY_PATTERN)-1, 0); result = php_pcre_replace(regex, - header, (int)strlen(header), + NULL, header, (int)strlen(header), &replace, 0, -1, NULL); + zval_ptr_dtor(&replace); + zend_string_release(regex); + if (NULL == result) { - zval_ptr_dtor(&replace); - zend_string_free(regex); return NULL; } @@ -184,12 +185,16 @@ static zend_string *php_win32_mail_trim_header(char *header) regex = zend_string_init(PHP_WIN32_MAIL_RMVDBL_PATTERN, sizeof(PHP_WIN32_MAIL_RMVDBL_PATTERN)-1, 0); result2 = php_pcre_replace(regex, - result->val, (int)result->len, + result, result->val, (int)result->len, &replace, 0, -1, NULL); - return result; + zval_ptr_dtor(&replace); + zend_string_release(regex); + zend_string_release(result); + + return result2; #else /* In case we don't have PCRE support (for whatever reason...) simply do nothing and return the unmodified header */ return estrdup(header); |