From 29f93f2dd070597096bd55602192b21b9912ecab Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sat, 22 Aug 2026 11:04:00 -0400 Subject: [PATCH] Fix user.ini handling when the script directory prefixes doc_root php_cgi_ini_activate_user_config() swapped the scan base when path was shorter than DOCUMENT_ROOT, so a script dir that prefixes doc_root never parsed .user.ini. Scan the tree only when path descends from doc_root; otherwise parse the current directory. Same change in sapi/cgi and sapi/fpm. --- sapi/cgi/cgi_main.c | 18 ++------ sapi/cgi/tests/user-ini-doc-root-prefix.phpt | 41 +++++++++++++++++ sapi/fpm/fpm/fpm_main.c | 20 +-------- sapi/fpm/tests/user-ini-doc-root-prefix.phpt | 47 ++++++++++++++++++++ 4 files changed, 93 insertions(+), 33 deletions(-) create mode 100644 sapi/cgi/tests/user-ini-doc-root-prefix.phpt create mode 100644 sapi/fpm/tests/user-ini-doc-root-prefix.phpt diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 0e7b3009c602..bd51e20d17e0 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -798,8 +798,6 @@ static void php_cgi_ini_activate_user_config(char *path, size_t path_len, const /* Check whether cache entry has expired and rescan if it is */ if (request_time > entry->expires) { char *real_path = NULL; - char *s1, *s2; - size_t s_len; /* Clear the expired config */ zend_hash_clean(entry->user_config); @@ -815,26 +813,16 @@ static void php_cgi_ini_activate_user_config(char *path, size_t path_len, const path_len = real_path_len; } - if (path_len > doc_root_len) { - s1 = (char *) doc_root; - s2 = path; - s_len = doc_root_len; - } else { - s1 = path; - s2 = (char *) doc_root; - s_len = path_len; - } - /* we have to test if path is part of DOCUMENT_ROOT. if it is inside the docroot, we scan the tree up to the docroot to find more user.ini, if not we only scan the current path. */ #ifdef PHP_WIN32 - if (strnicmp(s1, s2, s_len) == 0) { + if (path_len > doc_root_len && strnicmp(path, doc_root, doc_root_len) == 0) { #else - if (strncmp(s1, s2, s_len) == 0) { + if (path_len > doc_root_len && strncmp(path, doc_root, doc_root_len) == 0) { #endif - char *ptr = s2 + doc_root_len; + char *ptr = path + doc_root_len; #ifdef PHP_WIN32 while ((ptr = strpbrk(ptr, "\\/")) != NULL) { #else diff --git a/sapi/cgi/tests/user-ini-doc-root-prefix.phpt b/sapi/cgi/tests/user-ini-doc-root-prefix.phpt new file mode 100644 index 000000000000..532804a4eb35 --- /dev/null +++ b/sapi/cgi/tests/user-ini-doc-root-prefix.phpt @@ -0,0 +1,41 @@ +--TEST-- +CGI: user.ini is loaded when the script directory prefixes doc_root +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +X-Powered-By: PHP/%s +Content-type: text/html%r; charset=.*|%r + +77M +Done +--CLEAN-- + diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 56796c327f91..2d1305fafd78 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -653,8 +653,6 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha if (request_time > entry->expires) { char * real_path; int real_path_len; - char *s1, *s2; - int s_len; /* Clear the expired config */ zend_hash_clean(entry->user_config); @@ -669,22 +667,8 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha path_len = real_path_len; } - if (path_len > doc_root_len) { - s1 = (char *) doc_root; - s2 = path; - s_len = doc_root_len; - } else { - s1 = path; - s2 = (char *) doc_root; - s_len = path_len; - } - - /* we have to test if path is part of DOCUMENT_ROOT. - if it is inside the docroot, we scan the tree up to the docroot - to find more user.ini, if not we only scan the current path. - */ - if (strncmp(s1, s2, s_len) == 0) { - ptr = s2 + doc_root_len; + if (path_len > doc_root_len && strncmp(path, doc_root, doc_root_len) == 0) { + ptr = path + doc_root_len; while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) { *ptr = 0; php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config); diff --git a/sapi/fpm/tests/user-ini-doc-root-prefix.phpt b/sapi/fpm/tests/user-ini-doc-root-prefix.phpt new file mode 100644 index 000000000000..404f97e8984e --- /dev/null +++ b/sapi/fpm/tests/user-ini-doc-root-prefix.phpt @@ -0,0 +1,47 @@ +--TEST-- +FPM: user.ini is loaded when the script directory prefixes doc_root +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester + ->request(scriptFilename: $workDir . '/info.php', headers: ['DOCUMENT_ROOT' => $workDir . '/www']) + ->expectBody('77M'); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- +