php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81589 PHP script on FPM / FastCGI may end prematurely
Submitted: 2021-11-04 09:09 UTC Modified: 2021-11-04 09:58 UTC
From: peter dot kotuliak at gmail dot com Assigned:
Status: Duplicate Package: FPM related
PHP Version: Irrelevant OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: peter dot kotuliak at gmail dot com
New email:
PHP Version: OS:

 

 [2021-11-04 09:09 UTC] peter dot kotuliak at gmail dot com
Description:
------------
Running provided test script (error reporting cannot be Off) on real webserver (Apache, nginx tested) using php-fpm, ends prematurely.

This is FPM specific bug (e.g. use of Apache handler is OK).

Script "terminates" because FPM sometimes generates empty (zero length) FCGI record / packet. FCGI specification however states that such a record may indicate content termination.

Solution is to replace this code in fastcgi.c

	} else if (len - limit < (int)(sizeof(req->out_buf) - sizeof(fcgi_header))) {
		if (!req->out_hdr) {
			open_packet(req, type);
		}
		if (limit > 0) {
			memcpy(req->out_pos, str, limit);
			req->out_pos += limit;
		}
		if (!fcgi_flush(req, 0)) {

with this

	} else if (len - limit < (int)(sizeof(req->out_buf) - sizeof(fcgi_header))) {
		if (limit > 0) {
			if (!req->out_hdr) {
				open_packet(req, type);
			}
			memcpy(req->out_pos, str, limit);
			req->out_pos += limit;
		}
		if (!fcgi_flush(req, 0)) {


It solves bug, occurring when stream changes (from OUT to ERR or vice versa), but having too few bytes left in output buffer (in this case, first it is called close_packet due to stream change and since limit==0 additional open_packet and close_packet (inside fcgi_flush) is called with zero content length, which webserver interprets as "request finished").

Script has to be tested on real webserver (FPM tester used in .phpt does not copy webserver behavior that well in this case).
Every PHP version is affected. 
If you have any questions, or trouble reproducing bug, please contact me.

Test script:
---------------
<?php
for($i=0;$i<167;$i++){
    error_log('PHP is the best programming language');
}
echo 'end';
?>

Expected result:
----------------
string "end"

Actual result:
--------------
empty string

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-11-04 09:58 UTC] nikic@php.net
-Status: Open +Status: Duplicate
 [2021-11-04 09:58 UTC] nikic@php.net
This is the same issue as bug #72185, which also has a PR with the same fix you propose: https://github.com/php/php-src/pull/3198
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 01 17:01:32 2024 UTC