Bug #76058 [Opn->Csd]: After "POST data can't be buffered", using php://input makes huge tmp files
| From: | gwang@php.net | Date: | Thu, 04 Jul 2019 16:03:50 +0000 |
| Subject: | Bug #76058 [Opn->Csd]: After "POST data can't be buffered", using php://input makes huge tmp files | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-221635@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=76058&edit=1
ID: 76058
Updated by: gwang@php.net
Reported by: mwrusnak at gmail dot com
Summary: After "POST data can't be buffered", using
php://input makes huge tmp files
-Status: Open
+Status: Closed
Type: Bug
Package: Streams related
Operating System: linux
PHP Version: 7.1.15
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of gwang
Revision: http://git.php.net/?p=php-src.git;a=commit;h=32af676bd9f13815d40138a2299e862a3c6985cf
Log: Updated to LiteSpeed SAPI V7.4.3 Increased response header count limit from 100 to 1000. Added
crash handler to cleanly shutdown PHP request. Added CloudLinux mod_lsapi mode Fixed bug #76058
Previous Comments:
------------------------------------------------------------------------
[2018-03-06 01:55:20] mwrusnak at gmail dot com
Description:
------------
In the patch for bug #69487 (https://bugs.php.net/bug.php?id=69487), this PHP warning was added
"POST data can't be buffered; all data discarded", which works fine, but if
"php://input" is read after that occurs, it can sometimes make large temp files, often
multiple GB in size. If there is a timeout and PHP is killed while writing these files, they remain
in the temp directory.
I have only seen it happen when users have mod_lsapi from CloudLinux, but I can reproduce it with
the regular lsapi binary by sending a similar bad request. Using "strace", I copied what
the real LiteSpeed web server sent to lsphp during a normal POST request, then I sent the same
request to lsphp from a script, but without the POST body, and then killed the "sending"
end (normally LiteSpeed or mod_lsapi).
The initial cases I saw with this issue included logs from "strace", showing:
- A broken pipe when PHP tries to read the POST body from the web server
- The error message above
- A /tmp/phpxxxxxxx file being opened
- Huge volumes of data being written to that temp file's fd, when php://input is read.
As far as I can tell, the temp files are caused by php_stream_input_read() calling
php_stream_write(), while the data provided by sapi_read_post_block() (via the litespeed SAPI) is
bad, due to the broken pipe. The temp file content seems to be contents of memory, not part of a
HTTP POST request.
These are two discussions I know of, with some of the same users:
https://forums.cpanel.net/threads/big-phpxxxxxx-files-in-home-user-cagefs-tmp.609659/
https://wordpress.org/support/topic/big-phpxxxxxx-files-in-home-user-cagefs-tmp/
Though the issue is hard to reproduce on demand (and it doesn't seem that a .phpt could be
written for it), when the message "POST data can't be buffered; all data discarded"
occurs, and then the script tries to read "php://input", could PHP treat the input stream
as empty, without trying to read it again? Or is it better to prevent it in lsapi?
Test script:
---------------
Two scripts are here, one to run lsapi, and one to simulate a request from the web server:
https://github.com/mwrusnak/lsapi-issue-2018-03
(
strace output from monitoring the lsapi "index.html" script is also
included)
Expected result:
----------------
Reading "php://input" in a script should immediately return 0 bytes if the message
"POST data can't be buffered; all data discarded" has already occurred when PHP
originally tried to read the request body.
Actual result:
--------------
PHP writes a large temporary file with a name like /tmp/phpQQnomb, sometimes multiple GB in size.
Usually PHP is killed before the script finishes running.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=76058&edit=1