Skip to content

Commit

Permalink
Fix bug #74129: Incorrect SCRIPT_NAME with apache ProxyPassMatch
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bukka committed Mar 19, 2023
1 parent b5726c2 commit 0d4d471
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 3 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 23 additions & 3 deletions sapi/fpm/fpm/fpm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
54 changes: 54 additions & 0 deletions sapi/fpm/tests/fcgi-env-pif-apache-pp-sn-strip-encoded.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
--TEST--
FPM: FastCGI env var path info fix for Apache ProxyPass SCRIPT_NAME stripping with encoded path (bug #74129)
--SKIPIF--
<?php include "skipif.inc"; ?>
--FILE--
<?php

require_once "tester.inc";

$cfg = <<<EOT
[global]
error_log = {{FILE:LOG}}
[unconfined]
listen = {{ADDR}}
pm = dynamic
pm.max_children = 5
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[cgi.fix_pathinfo] = yes
EOT;

$code = <<<EOT
<?php
echo \$_SERVER["SCRIPT_NAME"] . "\n";
echo \$_SERVER["ORIG_SCRIPT_NAME"] . "\n";
echo \$_SERVER["SCRIPT_FILENAME"] . "\n";
echo \$_SERVER["PATH_INFO"] . "\n";
echo \$_SERVER["PHP_SELF"];
EOT;

$tester = new FPM\Tester($cfg, $code);
[$sourceFilePath, $scriptName] = $tester->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--
<?php
require_once "tester.inc";
FPM\Tester::clean();
?>

0 comments on commit 0d4d471

Please sign in to comment.