Skip to content

Commit f3c357c

Browse files
committed
Merge branch 'PHP-8.1'
2 parents f3a14d1 + bf97b36 commit f3c357c

File tree

7 files changed

+122
-16
lines changed

7 files changed

+122
-16
lines changed

main/SAPI.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ static void sapi_send_headers_free(void)
489489
}
490490
}
491491

492-
SAPI_API void sapi_deactivate(void)
492+
SAPI_API void sapi_deactivate_module(void)
493493
{
494494
zend_llist_destroy(&SG(sapi_headers).headers);
495495
if (SG(request_info).request_body) {
@@ -523,6 +523,10 @@ SAPI_API void sapi_deactivate(void)
523523
if (sapi_module.deactivate) {
524524
sapi_module.deactivate();
525525
}
526+
}
527+
528+
SAPI_API void sapi_deactivate_destroy(void)
529+
{
526530
if (SG(rfc1867_uploaded_files)) {
527531
destroy_uploaded_files_hash();
528532
}
@@ -537,6 +541,12 @@ SAPI_API void sapi_deactivate(void)
537541
SG(global_request_time) = 0;
538542
}
539543

544+
SAPI_API void sapi_deactivate(void)
545+
{
546+
sapi_deactivate_module();
547+
sapi_deactivate_destroy();
548+
}
549+
540550

541551
SAPI_API void sapi_initialize_empty_request(void)
542552
{

main/SAPI.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ extern SAPI_API sapi_globals_struct sapi_globals;
143143
SAPI_API void sapi_startup(sapi_module_struct *sf);
144144
SAPI_API void sapi_shutdown(void);
145145
SAPI_API void sapi_activate(void);
146+
SAPI_API void sapi_deactivate_module(void);
147+
SAPI_API void sapi_deactivate_destroy(void);
146148
SAPI_API void sapi_deactivate(void);
147149
SAPI_API void sapi_initialize_empty_request(void);
148150
SAPI_API void sapi_add_request_header(const char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);

main/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,10 +1865,12 @@ void php_request_shutdown(void *dummy)
18651865
zend_post_deactivate_modules();
18661866
} zend_end_try();
18671867

1868-
/* 12. SAPI related shutdown (free stuff) */
1868+
/* 12. SAPI related shutdown*/
18691869
zend_try {
1870-
sapi_deactivate();
1870+
sapi_deactivate_module();
18711871
} zend_end_try();
1872+
/* free SAPI stuff */
1873+
sapi_deactivate_destroy();
18721874

18731875
/* 13. free virtual CWD memory */
18741876
virtual_cwd_deactivate();
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
FPM: bug77780 - Headers already sent error incorrectly emitted
3+
--SKIPIF--
4+
<?php include "skipif.inc"; ?>
5+
--EXTENSIONS--
6+
session
7+
--FILE--
8+
<?php
9+
10+
require_once "tester.inc";
11+
12+
$cfg = <<<EOT
13+
[global]
14+
error_log = {{FILE:LOG}}
15+
[unconfined]
16+
listen = {{ADDR}}
17+
pm = static
18+
pm.max_children = 1
19+
EOT;
20+
21+
$code = <<<EOT
22+
<?php
23+
echo str_repeat('asdfghjkl', 150000) . "\n";
24+
EOT;
25+
26+
$tester = new FPM\Tester($cfg, $code);
27+
$tester->start();
28+
$tester->expectLogStartNotices();
29+
$tester
30+
->request(
31+
headers: [
32+
'PHP_VALUE' => "session.cookie_secure=1",
33+
],
34+
readLimit: 10,
35+
expectError: true
36+
);
37+
$tester->request(
38+
headers: [
39+
'PHP_VALUE' => "session.cookie_secure=1",
40+
]
41+
)
42+
->expectNoError();
43+
$tester->terminate();
44+
$tester->close();
45+
46+
?>
47+
Done
48+
--EXPECT--
49+
Done
50+
--CLEAN--
51+
<?php
52+
require_once "tester.inc";
53+
FPM\Tester::clean();
54+
?>

sapi/fpm/tests/fcgi.inc

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace Adoy\FastCGI;
2626

2727
class TimedOutException extends \Exception {}
2828
class ForbiddenException extends \Exception {}
29+
class ReadLimitExceeded extends \Exception {}
2930

3031
/**
3132
* Handles communication with a FastCGI application
@@ -404,16 +405,24 @@ class Client
404405
/**
405406
* Read a FastCGI Packet
406407
*
408+
* @param int $readLimit max content size
407409
* @return array
410+
* @throws ReadLimitExceeded
408411
*/
409-
private function readPacket()
412+
private function readPacket($readLimit = -1)
410413
{
411414
if ($packet = fread($this->_sock, self::HEADER_LEN)) {
412415
$resp = $this->decodePacketHeader($packet);
413416
$resp['content'] = '';
414417
if ($resp['contentLength']) {
415-
$len = $resp['contentLength'];
416-
while ($len && $buf=fread($this->_sock, $len)) {
418+
$len = $resp['contentLength'];
419+
if ($readLimit >= 0 && $len > $readLimit) {
420+
// close connection so it can be re-set reset and throw an error
421+
fclose($this->_sock);
422+
$this->_sock = null;
423+
throw new ReadLimitExceeded("Content has $len bytes but the limit is $readLimit bytes");
424+
}
425+
while ($len && $buf = fread($this->_sock, $len)) {
417426
$len -= strlen($buf);
418427
$resp['content'] .= $buf;
419428
}
@@ -473,15 +482,16 @@ class Client
473482
*
474483
* @param array $params Array of parameters
475484
* @param string $stdin Content
485+
* @param int $readLimit [optional] the number of bytes to accept in a single packet or -1 if unlimited
476486
* @return array
477487
* @throws ForbiddenException
478488
* @throws TimedOutException
479489
* @throws \Exception
480490
*/
481-
public function request_data(array $params, $stdin)
491+
public function request_data(array $params, $stdin, $readLimit = -1)
482492
{
483493
$id = $this->async_request($params, $stdin);
484-
return $this->wait_for_response_data($id);
494+
return $this->wait_for_response_data($id, 0, $readLimit);
485495
}
486496

487497
/**
@@ -579,12 +589,13 @@ class Client
579589
*
580590
* @param int $requestId
581591
* @param int $timeoutMs [optional] the number of milliseconds to wait.
592+
* @param int $readLimit [optional] the number of bytes to accept in a single packet or -1 if unlimited
582593
* @return array response data
583594
* @throws ForbiddenException
584595
* @throws TimedOutException
585596
* @throws \Exception
586597
*/
587-
public function wait_for_response_data($requestId, $timeoutMs = 0)
598+
public function wait_for_response_data($requestId, $timeoutMs = 0, $readLimit = -1)
588599
{
589600
if (!isset($this->_requests[$requestId])) {
590601
throw new \Exception('Invalid request id given');
@@ -608,7 +619,7 @@ class Client
608619
// but still not get the response requested
609620
$startTime = microtime(true);
610621

611-
while ($resp = $this->readPacket()) {
622+
while ($resp = $this->readPacket($readLimit)) {
612623
if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
613624
if ($resp['type'] == self::STDERR) {
614625
$this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_ERR;

sapi/fpm/tests/response.inc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,21 +111,31 @@ class Response
111111
}
112112

113113
/**
114-
* @param string $errorMessage
114+
* @param string|null $errorMessage
115115
* @return Response
116116
*/
117117
public function expectError($errorMessage)
118118
{
119119
$errorData = $this->getErrorData();
120120
if ($errorData !== $errorMessage) {
121-
$this->error(
122-
"The expected error message '$errorMessage' is not equal to returned error '$errorData'"
123-
);
121+
$expectedErrorMessage = $errorMessage !== null
122+
? "The expected error message '$errorMessage' is not equal to returned error '$errorData'"
123+
: "No error message expected but received '$errorData'";
124+
$this->error($expectedErrorMessage);
124125
}
125126

126127
return $this;
127128
}
128129

130+
/**
131+
* @param string $errorMessage
132+
* @return Response
133+
*/
134+
public function expectNoError()
135+
{
136+
return $this->expectError(null);
137+
}
138+
129139
/**
130140
* @param string $contentType
131141
* @return string|null

sapi/fpm/tests/tester.inc

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ class Tester
606606
* @param string|null $errorMessage
607607
* @param bool $connKeepAlive
608608
* @param string|null $scriptFilename = null
609+
* @param bool $expectError
610+
* @param int $readLimit
609611
* @return Response
610612
*/
611613
public function request(
@@ -617,7 +619,12 @@ class Tester
617619
string $errorMessage = null,
618620
bool $connKeepAlive = false,
619621
string $scriptFilename = null,
622+
<<<<<<< HEAD
620623
string $stdin = null
624+
=======
625+
bool $expectError = false,
626+
int $readLimit = -1,
627+
>>>>>>> PHP-8.1
621628
) {
622629
if ($this->hasError()) {
623630
return new Response(null, true);
@@ -627,11 +634,21 @@ class Tester
627634

628635
try {
629636
$this->response = new Response(
637+
<<<<<<< HEAD
630638
$this->getClient($address, $connKeepAlive)->request_data($params, $stdin)
639+
=======
640+
$this->getClient($address, $connKeepAlive)->request_data($params, false, $readLimit)
641+
>>>>>>> PHP-8.1
631642
);
632-
$this->message($successMessage);
643+
if ($expectError) {
644+
$this->error('Expected request error but the request was successful');
645+
} else {
646+
$this->message($successMessage);
647+
}
633648
} catch (\Exception $exception) {
634-
if ($errorMessage === null) {
649+
if ($expectError) {
650+
$this->message($successMessage);
651+
} elseif ($errorMessage === null) {
635652
$this->error("Request failed", $exception);
636653
} else {
637654
$this->message($errorMessage);

0 commit comments

Comments
 (0)