From 0d4d471847902dcb44d047d3bbf3f25f9aacdf88 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 12 Mar 2023 19:30:16 +0000 Subject: [PATCH] Fix bug #74129: Incorrect SCRIPT_NAME with apache ProxyPassMatch This happens when there are spaces are in the path info. The reason is that Apache decodes the path info part in the SCRIPT_NAME as per CGI RFC. FPM tries to strip path info from the SCRIPT_NAME but the comparison is done against SCRIPT_FILENAME which is not decoded. For that to work we have to decode it before comparison if there is any encoded character. Closes GH-10869 --- NEWS | 2 + sapi/fpm/fpm/fpm_main.c | 26 +++++++-- ...gi-env-pif-apache-pp-sn-strip-encoded.phpt | 54 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 sapi/fpm/tests/fcgi-env-pif-apache-pp-sn-strip-encoded.phpt diff --git a/NEWS b/NEWS index 5fe7729b8fb97..85bb5c240b715 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,8 @@ PHP NEWS - FPM: . Fixed bug GH-10611 (fpm_env_init_main leaks environ). (nielsdos) . Destroy file_handle in fpm_main. (Jakub Zelenka, nielsdos) + . Fixed bug #74129 (Incorrect SCRIPT_NAME with apache ProxyPassMatch when + spaces are in path). (Jakub Zelenka) - FTP: . Propagate success status of ftp_close(). (nielsdos) diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index aae4fea80b432..64ef27dadeb39 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1157,12 +1157,32 @@ static void init_request_info(void) * As we can extract PATH_INFO from PATH_TRANSLATED * it is probably also in SCRIPT_NAME and need to be removed */ - int snlen = strlen(env_script_name); - if (snlen>slen && !strcmp(env_script_name+snlen-slen, path_info)) { + char *decoded_path_info = NULL; + size_t decoded_path_info_len = 0; + if (strchr(path_info, '%')) { + decoded_path_info = estrdup(path_info); + decoded_path_info_len = php_url_decode(decoded_path_info, strlen(path_info)); + } + size_t snlen = strlen(env_script_name); + size_t env_script_file_info_start = 0; + if ( + ( + snlen > slen && + !strcmp(env_script_name + (env_script_file_info_start = snlen - slen), path_info) + ) || + ( + decoded_path_info && + snlen > decoded_path_info_len && + !strcmp(env_script_name + (env_script_file_info_start = snlen - decoded_path_info_len), decoded_path_info) + ) + ) { FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); - env_script_name[snlen-slen] = 0; + env_script_name[env_script_file_info_start] = 0; SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name); } + if (decoded_path_info) { + efree(decoded_path_info); + } } env_path_info = FCGI_PUTENV(request, "PATH_INFO", path_info); } diff --git a/sapi/fpm/tests/fcgi-env-pif-apache-pp-sn-strip-encoded.phpt b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sn-strip-encoded.phpt new file mode 100644 index 0000000000000..22114e1abde47 --- /dev/null +++ b/sapi/fpm/tests/fcgi-env-pif-apache-pp-sn-strip-encoded.phpt @@ -0,0 +1,54 @@ +--TEST-- +FPM: FastCGI env var path info fix for Apache ProxyPass SCRIPT_NAME stripping with encoded path (bug #74129) +--SKIPIF-- + +--FILE-- +createSourceFileAndScriptName(); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + uri: $scriptName . '/1%202', + scriptFilename: "proxy:fcgi://" . $tester->getAddr() . $sourceFilePath . '/1%202', + scriptName: $scriptName . '/1 2' + ) + ->expectBody([$scriptName, $scriptName . '/1 2', $sourceFilePath, '/1%202', $scriptName . '/1%202']); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- +