php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70470 Built-in server truncates headers spanning over TCP packets
Submitted: 2015-09-10 19:03 UTC Modified: 2015-09-11 14:35 UTC
Votes:10
Avg. Score:4.3 ± 0.9
Reproduced:10 of 10 (100.0%)
Same Version:2 (20.0%)
Same OS:2 (20.0%)
From: bwoebi@php.net Assigned:
Status: Closed Package: Built-in web server
PHP Version: 5.6.13 OS: Irrelevant
Private report: No CVE-ID:
 [2015-09-10 19:03 UTC] bwoebi@php.net
Description:
------------
The built-in server can truncate headers if they span over a TCP packet boundary.

Internally, it uses MARK(header_value) (Sets header_value_mark to the current pointer), then upon reaching the \r\n (in the next packet then, same buffer), but the \r\n will end up being before the header_value_mark pointer, thus ending up of never reading the part before the \r\n in the second packet.

Test script:
---------------
Use a valid header and ensure it's send in two different TCP packets to built-in server. Begin sending a header value in one packet and finish it in another. Then dump the header value.

Expected result:
----------------
Header value should be complete.

Actual result:
--------------
The header value is being truncated at the exact packet boundary.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-09-11 05:51 UTC] laruence@php.net
actually, not only header_value, but also header name, I committed a test script here: https://github.com/php/php-src/commit/37d814b84cff3678a2e1d56ea9d3ba3c35082e13

however, I don't see a good fix in the current implementation now... :<

thanks
 [2015-09-11 05:54 UTC] laruence@php.net
-Status: Open +Status: Verified
 [2015-09-11 14:35 UTC] bwoebi@php.net
The only solution is a different buffer… you may want to use a char[PHP_HTTP_MAX_HEADER_SIZE] allocated along with the client context, then copy in and out when you need to return. I don't really see a better way here...

check state at the end, copy if necessary… then on header value/name use that buffer then…
 [2015-09-11 14:35 UTC] bwoebi@php.net
The only solution is a different buffer… you may want to use a char[PHP_HTTP_MAX_HEADER_SIZE] allocated along with the client context, then copy in and out when you need to return. I don't really see a better way here...

check state at the end, copy if necessary… then on header value/name use that buffer then…
 [2016-01-29 02:22 UTC] cmstlist at gmail dot com
Just wanted to add, I am experiencing this while trying to get Google's Identity Framework ("Gitkit") Quick Start for PHP working on my local computer for a school project.
https://developers.google.com/identity/toolkit/web/quickstart/php

I have a test site set up to accept Facebook or Google logins. My code is not significantly modified from theirs aside from removing the "password" login option from the config array.

When logged in with my Facebook account, the Gitkit client-side JS library produces a 1015-character token that it stores in a cookie. Sporadically PHP truncates the token down to 310 characters or so, and as a result Google's OAuth2 library throws an exception (complaining the token does not have enough segments). Within a few refreshes it works again.

When logged in with my Google account the token is only about 896 characters long. This rarely gets truncated and thus rarely throws the same exception.
 [2017-09-04 15:08 UTC] bouke at shopify dot com
Hey y'all

I've made a patch that fixes this issue: https://github.com/php/php-src/pull/2736
 [2017-09-05 14:25 UTC] nikic@php.net
Automatic comment on behalf of boukevanderbijl@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cd9d90f4d41c87494dee8ee72c7a48951213296b
Log: Fixed bug #70470
 [2017-09-05 14:25 UTC] nikic@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC