summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2018-01-31 20:15:30 +0100
committerAnatol Belski <ab@php.net>2018-02-01 15:24:31 +0100
commitbced074124f65653071ccf29e0878ef725b09a49 (patch)
tree947e4209c826b56081caab942164ef9dfe298fa3
parentfe2ac52d508a450f8f7dea3f63e3b4763d1bd7e0 (diff)
downloadphp-git-bced074124f65653071ccf29e0878ef725b09a49.tar.gz
Fix race conditions with Apache vhost vs. per dir config
If the same php_value/php_flag is present in httpd.conf and .htaccess, the key is potentially shared between threads. Unfortunately we can't intern these keys using the current mechanism, because the MPM is setup before the SAPI module setup is even started. A more elegant way were to implement a kind of string pool for the thread safe Apache SAPI config directives with the mechanism similar to what is done for the SAPI setup now, but doing a separate management. (cherry picked from commit 73eb5a78b9caa18d35624765f9b972c1ba48855d)
-rw-r--r--sapi/apache2handler/apache_config.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c
index bd017535b8..05c9e85828 100644
--- a/sapi/apache2handler/apache_config.c
+++ b/sapi/apache2handler/apache_config.c
@@ -147,10 +147,28 @@ void config_entry_ctor(zval *zv)
void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf)
{
php_conf_rec *d = base_conf, *e = new_conf, *n = NULL;
+#ifdef ZTS
+ zend_string *str;
+ zval *data;
+#endif
n = create_php_config(p, "merge_php_config");
/* copy old config */
+#ifdef ZTS
+ ZEND_HASH_FOREACH_STR_KEY_VAL(&d->config, str, data) {
+ zend_string *key;
+ zval *new_entry;
+
+ /* Avoid sharing the non interned string among threads. */
+ key = zend_string_dup(str, 1);
+
+ new_entry = zend_hash_add(&n->config, key, data);
+
+ config_entry_ctor(new_entry);
+ } ZEND_HASH_FOREACH_END();
+#else
zend_hash_copy(&n->config, &d->config, config_entry_ctor);
+#endif
/* merge new config */
phpapdebug((stderr, "Merge dir (%p)+(%p)=(%p)\n", base_conf, new_conf, n));
zend_hash_merge_ex(&n->config, &e->config, config_entry_ctor, should_overwrite_per_dir_entry, NULL);