New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PHP processing a truncated POST request #12343
Comments
If anyone would like information on the story behind finding and investigating this behaviour, I've covered it in a two-part blog series so far: Part 1: https://scotthelme.co.uk/unravelling-mystery-of-truncated-post-requests-report-uri/ edit |
I'm aware of this issue and have got this note on my TODO list for some time:
I actually haven't created an issue for this yet so this is useful. I have got it quite high in terms of priority so will get to it in the next few months hopefully. |
So I have been looking into this and from the code this logic seems to be on purpose. It might be trying to follow this part of fcgi spec:
It kind of suggest that receiving less is possible / acceptable. There is however a recommendation (should) that states
It's not a complete requirement ( I actually realised that we already discussed it in #7509 . That PR is a good example of the client (nginx) that does not send any content length. Thinking about that one, it might make sense to allow missing content length together with this change so we don't introduce connection abort for chunked encoding. I think it also makes sense to add configuration to restore current behaviour in case there are some clients that would break otherwise. Just some sort of back up. |
Description
I've observed scenarios where PHP will read only a partial POST payload and begin processing it. The main scenario seems to be when Nginx times out on the
fastcgi_pass
to PHP, PHP will read whatever partial payload was written to the socket buffer and process it.The following code can reproduce the issue:
Send enough requests to exceed
pm.max_children
and cause a backlog. You can modifyfastcgi_connect_timeout
andfastcgi_send_timeout
to a lower value than default to exacerbate the issue for testing.I believe the issue is in the
read()
system call, which is returning0
before expected, but PHP does not check the size of the POST payload that was read against the declaredcontent-length
.php-src/main/fastcgi.c
Line 970 in 1c93cdc
The only validation of the size of the POST payload is in
SAPI_POST_READER_FUNC()
. This function initially checks the declaredcontent-length
does not exceedpost_max_size
, then reads the POST payload, and then checks the actual size of the POST payload that was read does not exceedpost_max_size
here.php-src/main/SAPI.c
Lines 282 to 285 in 1c93cdc
The error message is also misleading and could be updated. It implies that the check could detect a POST length longer or shorter than the declared
content-length
with "does not match", but actually it will only detect a scenario where the POST length is longer than declared. An error message like this would be more accurate.I created a patch for
SAPI.c
to demonstrate a possible behaviour and handling of the truncated POST payload that I might expect to see. This will check if the size of the POST payload read was smaller than the size declared incontent-length
and discard it if so.PHP Version
8.2.10
Operating System
Ubuntu 22.04 (LTS) x64
The text was updated successfully, but these errors were encountered: