diff options
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r-- | ext/pcre/php_pcre.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index d7a4309b24..7cc16ca6e6 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2014 The PHP Group | + | Copyright (c) 1997-2015 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -169,13 +169,14 @@ static PHP_MSHUTDOWN_FUNCTION(pcre) /* {{{ static pcre_clean_cache */ static int pcre_clean_cache(void *data, void *arg TSRMLS_DC) { + pcre_cache_entry *pce = (pcre_cache_entry *) data; int *num_clean = (int *)arg; - if (*num_clean > 0) { + if (*num_clean > 0 && !pce->refcount) { (*num_clean)--; - return 1; + return ZEND_HASH_APPLY_REMOVE; } else { - return 0; + return ZEND_HASH_APPLY_KEEP; } } /* }}} */ @@ -224,6 +225,25 @@ static char **make_subpats_table(int num_subpats, pcre_cache_entry *pce TSRMLS_D } /* }}} */ +/* {{{ static calculate_unit_length */ +/* Calculates the byte length of the next character. Assumes valid UTF-8 for PCRE_UTF8. */ +static zend_always_inline int calculate_unit_length(pcre_cache_entry *pce, char *start) +{ + int unit_len; + + if (pce->compile_options & PCRE_UTF8) { + char *end = start; + + /* skip continuation bytes */ + while ((*++end & 0xC0) == 0x80); + unit_len = end - start; + } else { + unit_len = 1; + } + return unit_len; +} +/* }}} */ + /* {{{ pcre_get_compiled_regex_cache */ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC) @@ -446,6 +466,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le new_entry.locale = pestrdup(locale, 1); new_entry.tables = tables; #endif + new_entry.refcount = 0; /* * Interned strings are not duplicated when stored in HashTable, @@ -550,8 +571,10 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ * RETURN_FALSE; } + pce->refcount++; php_pcre_match_impl(pce, subject, subject_len, return_value, subpats, global, ZEND_NUM_ARGS() >= 4, flags, start_offset TSRMLS_CC); + pce->refcount--; } /* }}} */ @@ -754,8 +777,10 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec the start offset, and continue. Fudge the offset values to achieve this, unless we're already at the end of the string. */ if (g_notempty != 0 && start_offset < subject_len) { + int unit_len = calculate_unit_length(pce, subject + start_offset); + offsets[0] = start_offset; - offsets[1] = start_offset + 1; + offsets[1] = start_offset + unit_len; } else break; } else { @@ -988,14 +1013,18 @@ PHPAPI char *php_pcre_replace(char *regex, int regex_len, int *result_len, int limit, int *replace_count TSRMLS_DC) { pcre_cache_entry *pce; /* Compiled regular expression */ + char *result; /* Function result */ /* Compile regex or get it from cache. */ if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) { return NULL; } - - return php_pcre_replace_impl(pce, subject, subject_len, replace_val, + pce->refcount++; + result = php_pcre_replace_impl(pce, subject, subject_len, replace_val, is_callable_replace, result_len, limit, replace_count TSRMLS_CC); + pce->refcount--; + + return result; } /* }}} */ @@ -1052,6 +1081,10 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub replace_end = replace + replace_len; } + if (eval) { + php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The /e modifier is deprecated, use preg_replace_callback instead"); + } + /* Calculate the size of the offsets array, and allocate memory for it. */ rc = pcre_fullinfo(pce->re, extra, PCRE_INFO_CAPTURECOUNT, &num_subpats); if (rc < 0) { @@ -1194,10 +1227,12 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub the start offset, and continue. Fudge the offset values to achieve this, unless we're already at the end of the string. */ if (g_notempty != 0 && start_offset < subject_len) { + int unit_len = calculate_unit_length(pce, piece); + offsets[0] = start_offset; - offsets[1] = start_offset + 1; - memcpy(&result[*result_len], piece, 1); - (*result_len)++; + offsets[1] = start_offset + unit_len; + memcpy(&result[*result_len], piece, unit_len); + *result_len += unit_len; } else { new_len = *result_len + subject_len - start_offset; if (new_len + 1 > alloc_len) { @@ -1472,7 +1507,9 @@ static PHP_FUNCTION(preg_split) RETURN_FALSE; } + pce->refcount++; php_pcre_split_impl(pce, subject, subject_len, return_value, limit_val, flags TSRMLS_CC); + pce->refcount--; } /* }}} */ @@ -1752,8 +1789,10 @@ static PHP_FUNCTION(preg_grep) if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) { RETURN_FALSE; } - + + pce->refcount++; php_pcre_grep_impl(pce, input, return_value, flags TSRMLS_CC); + pce->refcount--; } /* }}} */ |