summaryrefslogtreecommitdiff
path: root/ext/pcre/php_pcre.c
diff options
context:
space:
mode:
authorJoe Watkins <krakjoe@php.net>2017-01-02 09:44:02 +0000
committerJoe Watkins <krakjoe@php.net>2017-01-02 09:44:02 +0000
commit3e798c4a5f143ca46feab994d5f446c15aef8e98 (patch)
treee1196b654c889dc5de45fda5c99a2d1873a4008f /ext/pcre/php_pcre.c
parente077735b03fd2339b2d663d29557cfb5ab2d5eff (diff)
parent935b5cb11ed672c42b2a77e10be752702e474e7f (diff)
downloadphp-git-3e798c4a5f143ca46feab994d5f446c15aef8e98.tar.gz
Merge branch 'PHP-7.0' of git.php.net:/php-src into PHP-7.0
* 'PHP-7.0' of git.php.net:/php-src: (146 commits) Flush stderr on win32 in cli_log_message Fixed bug #73154 FIx bug #70213 Fix dom class can't be inherited by the internal class Another try at making concat_003 more reliable Fix flaky openssl_pkey_new test Make Opcache tests using the cli server more reliable Revert "Fix #73530: Unsetting result set may reset other result set" define php_ap_map_http_request_error function for older httpd only add old versions of httpd support Disable AppVeyor fast_finish Makes the sapi web server and curl tests more reliable Fixes the curl tests to be more reliable in Travis CI Interpretation of curl_setopt values for boolean parameters Fixes #65689. PDO_Firebrid / exec() does not free allocated statement. Fix alpn_ctx leaking in openssl Fixed bug #73373 (deflate_add does not verify that output was not truncated) Fix IS_UNDEF comparisons in opcache Fixed bug #73704 (phpdbg shows the wrong line in files with shebang) Increase timing quota for small string concat test ...
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r--ext/pcre/php_pcre.c107
1 files changed, 70 insertions, 37 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index b1ffe7f228..af1916aa45 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -114,9 +114,6 @@ static void php_free_pcre_cache(zval *data) /* {{{ */
}
#if HAVE_SETLOCALE
if ((void*)pce->tables) pefree((void*)pce->tables, 1);
- if (pce->locale) {
- zend_string_release(pce->locale);
- }
#endif
pefree(pce, 1);
}
@@ -320,27 +317,30 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
pcre_cache_entry *pce;
pcre_cache_entry new_entry;
int rc;
+ zend_string *key;
+
+#if HAVE_SETLOCALE
+ if (BG(locale_string) &&
+ (ZSTR_LEN(BG(locale_string)) != 1 && ZSTR_VAL(BG(locale_string))[0] != 'C')) {
+ key = zend_string_alloc(ZSTR_LEN(regex) + ZSTR_LEN(BG(locale_string)) + 1, 0);
+ memcpy(ZSTR_VAL(key), ZSTR_VAL(BG(locale_string)), ZSTR_LEN(BG(locale_string)) + 1);
+ memcpy(ZSTR_VAL(key) + ZSTR_LEN(BG(locale_string)), ZSTR_VAL(regex), ZSTR_LEN(regex) + 1);
+ } else
+#endif
+ {
+ key = regex;
+ }
/* Try to lookup the cached regex entry, and if successful, just pass
back the compiled pattern, otherwise go on and compile it. */
- pce = zend_hash_find_ptr(&PCRE_G(pcre_cache), regex);
+ pce = zend_hash_find_ptr(&PCRE_G(pcre_cache), key);
if (pce) {
#if HAVE_SETLOCALE
- if (pce->locale == BG(locale_string) ||
- (pce->locale && BG(locale_string) &&
- ZSTR_LEN(pce->locale) == ZSTR_LEN(BG(locale_string)) &&
- !memcmp(ZSTR_VAL(pce->locale), ZSTR_VAL(BG(locale_string)), ZSTR_LEN(pce->locale))) ||
- (!pce->locale &&
- ZSTR_LEN(BG(locale_string)) == 1 &&
- ZSTR_VAL(BG(locale_string))[0] == 'C') ||
- (!BG(locale_string) &&
- ZSTR_LEN(pce->locale) == 1 &&
- ZSTR_VAL(pce->locale)[0] == 'C')) {
- return pce;
+ if (key != regex) {
+ zend_string_release(key);
}
-#else
- return pce;
#endif
+ return pce;
}
p = ZSTR_VAL(regex);
@@ -349,6 +349,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
get to the end without encountering a delimiter. */
while (isspace((int)*(unsigned char *)p)) p++;
if (*p == 0) {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
php_error_docref(NULL, E_WARNING,
p < ZSTR_VAL(regex) + ZSTR_LEN(regex) ? "Null byte in regex" : "Empty regular expression");
return NULL;
@@ -358,6 +363,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
or a backslash. */
delimiter = *p++;
if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
php_error_docref(NULL,E_WARNING, "Delimiter must not be alphanumeric or backslash");
return NULL;
}
@@ -397,6 +407,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
}
if (*pp == 0) {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
if (pp < ZSTR_VAL(regex) + ZSTR_LEN(regex)) {
php_error_docref(NULL,E_WARNING, "Null byte in regex");
} else if (start_delimiter == end_delimiter) {
@@ -453,13 +468,17 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
php_error_docref(NULL,E_WARNING, "Null byte in regex");
}
efree(pattern);
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
return NULL;
}
}
#if HAVE_SETLOCALE
- if (BG(locale_string) &&
- (ZSTR_LEN(BG(locale_string)) != 1 || ZSTR_VAL(BG(locale_string))[0] != 'C')) {
+ if (key != regex) {
tables = pcre_maketables();
}
#endif
@@ -472,6 +491,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
tables);
if (re == NULL) {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
php_error_docref(NULL,E_WARNING, "Compilation failed: %s at offset %d", error, erroffset);
efree(pattern);
if (tables) {
@@ -516,7 +540,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
* these are supposedly the oldest ones (but not necessarily the least used
* ones).
*/
- if (zend_hash_num_elements(&PCRE_G(pcre_cache)) == PCRE_CACHE_SIZE) {
+ if (!pce && zend_hash_num_elements(&PCRE_G(pcre_cache)) == PCRE_CACHE_SIZE) {
int num_clean = PCRE_CACHE_SIZE / 8;
zend_hash_apply_with_argument(&PCRE_G(pcre_cache), pcre_clean_cache, &num_clean);
}
@@ -527,23 +551,29 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
new_entry.preg_options = poptions;
new_entry.compile_options = coptions;
#if HAVE_SETLOCALE
- new_entry.locale = BG(locale_string) ?
- ((GC_FLAGS(BG(locale_string)) & IS_STR_PERSISTENT) ?
- zend_string_copy(BG(locale_string)) :
- zend_string_init(ZSTR_VAL(BG(locale_string)), ZSTR_LEN(BG(locale_string)), 1)) :
- NULL;
+ new_entry.locale = NULL;
new_entry.tables = tables;
#endif
new_entry.refcount = 0;
rc = pcre_fullinfo(re, extra, PCRE_INFO_CAPTURECOUNT, &new_entry.capture_count);
if (rc < 0) {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc);
return NULL;
}
rc = pcre_fullinfo(re, extra, PCRE_INFO_NAMECOUNT, &new_entry.name_count);
if (rc < 0) {
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc);
return NULL;
}
@@ -556,15 +586,18 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
* as hash keys especually for this table.
* See bug #63180
*/
- if (!ZSTR_IS_INTERNED(regex) || !(GC_FLAGS(regex) & IS_STR_PERMANENT)) {
- zend_string *str = zend_string_init(ZSTR_VAL(regex), ZSTR_LEN(regex), 1);
- GC_REFCOUNT(str) = 0; /* will be incremented by zend_hash_update_mem() */
- ZSTR_H(str) = ZSTR_H(regex);
- regex = str;
+ if (!ZSTR_IS_INTERNED(key) || !(GC_FLAGS(key) & IS_STR_PERMANENT)) {
+ pce = zend_hash_str_update_mem(&PCRE_G(pcre_cache),
+ ZSTR_VAL(key), ZSTR_LEN(key), &new_entry, sizeof(pcre_cache_entry));
+#if HAVE_SETLOCALE
+ if (key != regex) {
+ zend_string_release(key);
+ }
+#endif
+ } else {
+ pce = zend_hash_update_mem(&PCRE_G(pcre_cache), key, &new_entry, sizeof(pcre_cache_entry));
}
- pce = zend_hash_update_mem(&PCRE_G(pcre_cache), regex, &new_entry, sizeof(pcre_cache_entry));
-
return pce;
}
/* }}} */
@@ -693,7 +726,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
/* Overwrite the passed-in value for subpatterns with an empty array. */
if (subpats != NULL) {
- zval_dtor(subpats);
+ zval_ptr_dtor(subpats);
array_init(subpats);
}
@@ -1559,7 +1592,7 @@ static PHP_FUNCTION(preg_replace)
replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 0, 0);
if (zcount) {
- zval_dtor(zcount);
+ zval_ptr_dtor(zcount);
ZVAL_LONG(zcount, replace_count);
}
}
@@ -1594,7 +1627,7 @@ static PHP_FUNCTION(preg_replace_callback)
replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 1, 0);
if (zcount) {
- zval_dtor(zcount);
+ zval_ptr_dtor(zcount);
ZVAL_LONG(zcount, replace_count);
}
}
@@ -1656,7 +1689,7 @@ static PHP_FUNCTION(preg_replace_callback_array)
} ZEND_HASH_FOREACH_END();
if (zcount) {
- zval_dtor(zcount);
+ zval_ptr_dtor(zcount);
ZVAL_LONG(zcount, replace_count);
}
}
@@ -1687,7 +1720,7 @@ static PHP_FUNCTION(preg_filter)
replace_count = preg_replace_impl(return_value, regex, replace, subject, limit, 0, 1);
if (zcount) {
- zval_dtor(zcount);
+ zval_ptr_dtor(zcount);
ZVAL_LONG(zcount, replace_count);
}
}