php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78719 fopen() http wrapper silently ignores long Location headers
Submitted: 2019-10-22 13:36 UTC Modified: 2021-02-08 17:24 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: riikka dot kalliomaki at gmail dot com Assigned: cmb (profile)
Status: Closed Package: HTTP related
PHP Version: 7.3.10 OS:
Private report: No CVE-ID: None
 [2019-10-22 13:36 UTC] riikka dot kalliomaki at gmail dot com
Description:
------------
It seems that when a long enough URL is passed in the "Location" for redirection, PHP simply ignores the header.

Looking further into the source code, it seems that internally in the HTTP wrapper for fopen() "php_stream_url_wrap_http_ex" reads the headers from requests into a buffer that is allocated 1024 bytes (HTTP_HEADER_BLOCK_SIZE). Any header that is longer than that seems to be silently ignored.

This limit of 1024 characters is particularly limiting when it comes to URLs. While there isn't really any specific maximum length of URLs, when googling "maximum url length", the most common recommended answer is "2,048 characters".

What makes this worse is that the header is simply silently ignored. No notices, warnings or anything. This can stop a simple redirection chain simply because the url was a bit long and give no details about what went wrong. Looking at the stream with stream_get_meta_data() will not even display the long header, so it looks to the user like the header was never received.

IMO, the HTTP wrapper should at least be able to handle location headers with URLs that are 2048 characters long. Additionally, it may be prudent to trigger a notice or warning if a header is ignored and it may have affected the result instead of just silently ignoring it.

Test script:
---------------
Set up a remote test script like:

<?php

if (isset($_GET['r'])) {
  echo 'Redirect Succesful' . PHP_EOL;
} elseif (isset($_GET['length'])) {
  $header = 'Location: https://etc.riimu.net/redirect_test.php?r=';
  $length = strlen($header) + 2; // Account for \r\n
  $requested = max(0, (int)$_GET['length']);

  if ($requested < $length) {
    http_response_code(400);
    printf('Cannot create header shorter than %d due to prefix "%s"' . PHP_EOL, $length, $header);
  } else {
    header($header . str_repeat('a', $requested - $length), true, 302);
    echo "Redirect Failed" . PHP_EOL;
  }
} else {
  echo "Usage: Set 'length' GET parameter to desired Location header line length" . PHP_EOL;
}

And then run on your local machine like:

<?php

echo file_get_contents('https://etc.riimu.net/redirect_test.php?length=1023');
echo file_get_contents('https://etc.riimu.net/redirect_test.php?length=1024');

Expected result:
----------------
Redirect Succesful
Redirect Succesful

Actual result:
--------------
Redirect Succesful
Redirect Failed

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-08 17:24 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: cmb
 [2021-02-08 17:24 UTC] cmb@php.net
RFC 7230, section 3.2.5[1] states:

| A client MAY discard or truncate received header fields that are
| larger than the client wishes to process if the field semantics
| are such that the dropped value(s) can be safely ignored without
| changing the message framing or response semantics.

At least if follow_location is set, discarding the location header
would violate the RFC.

[1] <https://tools.ietf.org/html/rfc7230#section-3.2.5>
 [2021-02-09 11:31 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #78719: http wrapper silently ignores long Location headers
On GitHub:  https://github.com/php/php-src/pull/6676
Patch:      https://github.com/php/php-src/pull/6676.patch
 [2021-02-23 14:37 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #78719: http wrapper silently ignores long Location headers
On GitHub:  https://github.com/php/php-src/pull/6720
Patch:      https://github.com/php/php-src/pull/6720.patch
 [2021-03-03 09:49 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=51e2015af3fc4757a666736aae7899a43f76ae6d
Log: Fix #78719: http wrapper silently ignores long Location headers
 [2021-03-03 09:49 UTC] cmb@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 11:01:30 2024 UTC