summaryrefslogtreecommitdiff
path: root/ext/pcre/php_pcre.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r--ext/pcre/php_pcre.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 79679e59e7..36dda6deb5 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -55,9 +55,6 @@ struct _pcre_cache_entry {
uint32_t compile_options;
uint32_t extra_compile_options;
uint32_t refcount;
-#if HAVE_SETLOCALE
- const uint8_t *tables;
-#endif
};
enum {
@@ -100,6 +97,16 @@ static MUTEX_T pcre_mt = NULL;
#define php_pcre_mutex_unlock()
#endif
+#if HAVE_SETLOCALE
+ZEND_TLS HashTable char_tables;
+
+static void php_pcre_free_char_table(zval *data)
+{/*{{{*/
+ void *ptr = Z_PTR_P(data);
+ pefree(ptr, 1);
+}/*}}}*/
+#endif
+
static void pcre_handle_exec_error(int pcre_code) /* {{{ */
{
int preg_code = 0;
@@ -141,9 +148,6 @@ static void php_free_pcre_cache(zval *data) /* {{{ */
pcre_cache_entry *pce = (pcre_cache_entry *) Z_PTR_P(data);
if (!pce) return;
pcre2_code_free(pce->re);
-#if HAVE_SETLOCALE
- if ((void*)pce->tables) pefree((void*)pce->tables, 1);
-#endif
pefree(pce, 1);
}
/* }}} */
@@ -262,6 +266,9 @@ static PHP_GINIT_FUNCTION(pcre) /* {{{ */
#endif
php_pcre_init_pcre2(1);
+#if HAVE_SETLOCALE
+ zend_hash_init(&char_tables, 1, NULL, php_pcre_free_char_table, 1);
+#endif
}
/* }}} */
@@ -270,6 +277,9 @@ static PHP_GSHUTDOWN_FUNCTION(pcre) /* {{{ */
zend_hash_destroy(&pcre_globals->pcre_cache);
php_pcre_shutdown_pcre2();
+#if HAVE_SETLOCALE
+ zend_hash_destroy(&char_tables);
+#endif
php_pcre_mutex_free();
}
@@ -535,6 +545,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
size_t pattern_len;
uint32_t poptions = 0;
const uint8_t *tables = NULL;
+ uint8_t save_tables = 0;
zval *zv;
pcre_cache_entry new_entry;
int rc;
@@ -705,13 +716,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
#if HAVE_SETLOCALE
if (key != regex) {
- /* XXX a better solution here were to create a copy of cctx
- and to cache it along with the generated tables. Once same locale
- is encountered, the cached cctx and tables would be fetched.
- Currently the tables are generated every time a locale based
- pattern is used, and the tables are overwritten in the global
- cctx. */
- tables = pcre2_maketables(gctx);
+ tables = (uint8_t *)zend_hash_find_ptr(&char_tables, BG(locale_string));
+ if (!tables) {
+ save_tables = 1;
+ tables = pcre2_maketables(gctx);
+ }
pcre2_set_character_tables(cctx, tables);
}
#endif
@@ -739,7 +748,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
php_error_docref(NULL,E_WARNING, "Compilation failed: %s at offset %zu", error, erroffset);
pcre_handle_exec_error(PCRE2_ERROR_INTERNAL);
efree(pattern);
- if (tables) {
+ if (save_tables) {
pefree((void*)tables, 1);
}
return NULL;
@@ -779,7 +788,9 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
new_entry.compile_options = coptions;
new_entry.extra_compile_options = extra_coptions;
#if HAVE_SETLOCALE
- new_entry.tables = tables;
+ if (save_tables) {
+ zend_hash_add_ptr(&char_tables, BG(locale_string), (void *)tables);
+ }
#endif
new_entry.refcount = 0;