Created
November 14, 2016 04:33
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c | |
index b1ffe7f..2609a0b 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,27 @@ 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)), 0); | |
+ memcpy(ZSTR_VAL(key), ZSTR_VAL(BG(locale_string)), ZSTR_LEN(BG(locale_string))); | |
+ memcpy(ZSTR_VAL(key) + ZSTR_LEN(BG(locale_string)), ZSTR_VAL(regex), ZSTR_LEN(regex) + 1); | |
+ } else { | |
+ key = regex; | |
+ } | |
+#else | |
+ key = regex; | |
+#endif | |
/* 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; | |
- } | |
-#else | |
return pce; | |
-#endif | |
} | |
p = ZSTR_VAL(regex); | |
@@ -349,6 +346,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 +360,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; | |
} | |
@@ -404,6 +411,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) | |
} else { | |
php_error_docref(NULL,E_WARNING, "No ending matching delimiter '%c' found", delimiter); | |
} | |
+#if HAVE_SETLOCALE | |
+ if (key != regex) { | |
+ zend_string_release(key); | |
+ } | |
+#endif | |
return NULL; | |
} | |
@@ -453,13 +465,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 | |
@@ -477,6 +493,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) | |
if (tables) { | |
pefree((void*)tables, 1); | |
} | |
+#if HAVE_SETLOCALE | |
+ if (key != regex) { | |
+ zend_string_release(key); | |
+ } | |
+#endif | |
return NULL; | |
} | |
@@ -527,11 +548,7 @@ 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; | |
@@ -539,31 +556,32 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) | |
rc = pcre_fullinfo(re, extra, PCRE_INFO_CAPTURECOUNT, &new_entry.capture_count); | |
if (rc < 0) { | |
php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc); | |
+#if HAVE_SETLOCALE | |
+ if (key != regex) { | |
+ zend_string_release(key); | |
+ } | |
+#endif | |
return NULL; | |
} | |
rc = pcre_fullinfo(re, extra, PCRE_INFO_NAMECOUNT, &new_entry.name_count); | |
if (rc < 0) { | |
php_error_docref(NULL, E_WARNING, "Internal pcre_fullinfo() error %d", rc); | |
+#if HAVE_SETLOCALE | |
+ if (key != regex) { | |
+ zend_string_release(key); | |
+ } | |
+#endif | |
return NULL; | |
} | |
- /* | |
- * Interned strings are not duplicated when stored in HashTable, | |
- * but all the interned strings created during HTTP request are removed | |
- * at end of request. However PCRE_G(pcre_cache) must be consistent | |
- * on the next request as well. So we disable usage of interned strings | |
- * 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; | |
- } | |
+ pce = zend_hash_str_update_mem(&PCRE_G(pcre_cache), ZSTR_VAL(key), ZSTR_LEN(key), &new_entry, sizeof(pcre_cache_entry)); | |
- pce = zend_hash_update_mem(&PCRE_G(pcre_cache), regex, &new_entry, sizeof(pcre_cache_entry)); | |
+#if HAVE_SETLOCALE | |
+ if (key != regex) { | |
+ zend_string_release(key); | |
+ } | |
+#endif | |
return pce; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment