summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2018-01-31 20:15:30 +0100
committerAnatol Belski <ab@php.net>2018-01-31 20:15:30 +0100
commit73eb5a78b9caa18d35624765f9b972c1ba48855d (patch)
tree038fe4184349d1f6c1b3c0ce103865f6e3e4637d
parent5feb53964fad1c483fc64fa5c40e0c3f7fcc9ed9 (diff)
downloadphp-git-73eb5a78b9caa18d35624765f9b972c1ba48855d.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.
-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);