Skip to content

Commit 891b58d

Browse files
committed
Fix bug #77106: Missing separator in FPM FastCGI errors
1 parent 6b212b6 commit 891b58d

File tree

4 files changed

+94
-7
lines changed

4 files changed

+94
-7
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.2
44

5+
- FPM:
6+
. Fixed bug #77106 (Missing separator in FPM FastCGI errors). (Jakub Zelenka)
7+
58
- LDAP:
69
. Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()).
710
(cmb)

sapi/fpm/fpm/fpm_main.c

+12-4
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ typedef struct _php_cgi_globals_struct {
149149
bool force_redirect;
150150
bool discard_path;
151151
bool fcgi_logging;
152+
bool fcgi_logging_request_started;
152153
char *redirect_status_env;
153154
HashTable user_config_cache;
154155
char *error_header;
@@ -598,11 +599,16 @@ void sapi_cgi_log_fastcgi(int level, char *message, size_t len)
598599
* - logging is enabled (fastcgi.logging in php.ini)
599600
* - we are currently dealing with a request
600601
* - the message is not empty
601-
* - the fcgi_write did not fail
602602
*/
603-
if (CGIG(fcgi_logging) && request && message && len > 0
604-
&& fcgi_write(request, FCGI_STDERR, message, len) < 0) {
605-
php_handle_aborted_connection();
603+
if (CGIG(fcgi_logging) && request && message && len > 0) {
604+
if (CGIG(fcgi_logging_request_started)) {
605+
fcgi_write(request, FCGI_STDERR, "; ", 2);
606+
} else {
607+
CGIG(fcgi_logging_request_started) = true;
608+
}
609+
if (fcgi_write(request, FCGI_STDERR, message, len) < 0) {
610+
php_handle_aborted_connection();
611+
}
606612
}
607613
}
608614
/* }}} */
@@ -1403,6 +1409,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals)
14031409
php_cgi_globals->fix_pathinfo = 1;
14041410
php_cgi_globals->discard_path = 0;
14051411
php_cgi_globals->fcgi_logging = 1;
1412+
php_cgi_globals->fcgi_logging_request_started = false;
14061413
zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, user_config_cache_entry_dtor, 1);
14071414
php_cgi_globals->error_header = NULL;
14081415
php_cgi_globals->fpm_config = NULL;
@@ -1820,6 +1827,7 @@ consult the installation file that came with this distribution, or visit \n\
18201827
char *primary_script = NULL;
18211828
request_body_fd = -1;
18221829
SG(server_context) = (void *) request;
1830+
CGIG(fcgi_logging_request_started) = false;
18231831
init_request_info();
18241832

18251833
fpm_request_info();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
FPM: bug77106 - Missing new lines in FCGI error stream
3+
--SKIPIF--
4+
<?php include "skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
8+
require_once "tester.inc";
9+
10+
$cfg = <<<EOT
11+
[global]
12+
error_log = {{FILE:LOG}}
13+
[unconfined]
14+
listen = {{ADDR}}
15+
pm = dynamic
16+
pm.max_children = 5
17+
pm.start_servers = 1
18+
pm.min_spare_servers = 1
19+
pm.max_spare_servers = 3
20+
php_admin_flag[log_errors] = 1
21+
EOT;
22+
23+
$code = <<<EOT
24+
<?php
25+
echo \$a;
26+
echo \$a;
27+
EOT;
28+
29+
$tester = new FPM\Tester($cfg, $code);
30+
$tester->start();
31+
$tester->expectLogStartNotices();
32+
$tester->request()->expectErrorPattern(
33+
'/Undefined variable \$a in .+ on line \d+; PHP message: PHP Warning:/'
34+
);
35+
$tester->terminate();
36+
$tester->close();
37+
38+
?>
39+
Done
40+
--EXPECT--
41+
Done
42+
--CLEAN--
43+
<?php
44+
require_once "tester.inc";
45+
FPM\Tester::clean();
46+
?>

sapi/fpm/tests/response.inc

+33-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ class Response
4141
*/
4242
private $expectInvalid;
4343

44+
/**
45+
* @var bool
46+
*/
47+
private bool $debugOutputted = false;
48+
4449
/**
4550
* @param string|array|null $data
4651
* @param bool $expectInvalid
@@ -71,9 +76,9 @@ class Response
7176
$body = implode("\n", $body);
7277
}
7378

74-
if (!$this->checkIfValid()) {
79+
if ( ! $this->checkIfValid()) {
7580
$this->error('Response is invalid');
76-
} elseif (!$this->checkDefaultHeaders($contentType)) {
81+
} elseif ( ! $this->checkDefaultHeaders($contentType)) {
7782
$this->error('Response default headers not found');
7883
} elseif ($body !== $this->rawBody) {
7984
if ($multiLine) {
@@ -134,6 +139,26 @@ class Response
134139
return $this;
135140
}
136141

142+
/**
143+
* Expect error pattern in the response.
144+
*
145+
* @param string $errorMessagePattern Expected error message RegExp patter.
146+
*
147+
* @return Response
148+
*/
149+
public function expectErrorPattern(string $errorMessagePattern): Response
150+
{
151+
$errorData = $this->getErrorData();
152+
if (preg_match($errorMessagePattern, $errorData) === 0) {
153+
$this->error(
154+
"The expected error pattern $errorMessagePattern does not match the returned error '$errorData'"
155+
);
156+
$this->debugOutput();
157+
}
158+
159+
return $this;
160+
}
161+
137162
/**
138163
* Expect no error in the response.
139164
*
@@ -187,6 +212,8 @@ class Response
187212
echo "----------------- ERR -----------------\n";
188213
echo $this->data['err_response'] . "\n";
189214
echo "---------------------------------------\n\n";
215+
216+
$this->debugOutputted = true;
190217
}
191218

192219
/**
@@ -331,8 +358,11 @@ class Response
331358
*
332359
* @return bool
333360
*/
334-
private function error($message): bool
361+
private function error(string $message): bool
335362
{
363+
if ( ! $this->debugOutputted) {
364+
$this->debugOutput();
365+
}
336366
echo "ERROR: $message\n";
337367

338368
return false;

0 commit comments

Comments
 (0)