Bug #78719 [NEW]: fopen() http wrapper silently ignores long Location headers

From: Date: Tue, 22 Oct 2019 13:36:52 +0000
Subject: Bug #78719 [NEW]: fopen() http wrapper silently ignores long Location headers
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-223379@lists.php.net to get a copy of this message
From:             riikka dot kalliomaki at gmail dot com
Operating system: 
PHP version:      7.3.10
Package:          HTTP related
Bug Type:         Bug
Bug description:fopen() http wrapper silently ignores long Location headers

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

-- 
Edit bug report at https://bugs.php.net/bug.php?id=78719&edit=1
-- 
Fix committed:                    https://bugs.php.net/fix.php?id=78719&r=fixed
Fixed in release:                 https://bugs.php.net/fix.php?id=78719&r=alreadyfixed
Need backtrace:                   https://bugs.php.net/fix.php?id=78719&r=needtrace
Need Reproduce Script:            https://bugs.php.net/fix.php?id=78719&r=needscript
Try newer version:                https://bugs.php.net/fix.php?id=78719&r=oldversion
Not developer issue:              https://bugs.php.net/fix.php?id=78719&r=support
Expected behavior:                https://bugs.php.net/fix.php?id=78719&r=notwrong
Not enough info:                  https://bugs.php.net/fix.php?id=78719&r=notenoughinfo
Submitted twice:                  https://bugs.php.net/fix.php?id=78719&r=submittedtwice
register_globals:                 https://bugs.php.net/fix.php?id=78719&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=78719&r=phptooold
Daylight Savings:                 https://bugs.php.net/fix.php?id=78719&r=dst
IIS Stability:                    https://bugs.php.net/fix.php?id=78719&r=isapi
Install GNU Sed:                  https://bugs.php.net/fix.php?id=78719&r=gnused
Floating point limitations:       https://bugs.php.net/fix.php?id=78719&r=float
No Zend Extensions:               https://bugs.php.net/fix.php?id=78719&r=nozend
MySQL Configuration Error:        https://bugs.php.net/fix.php?id=78719&r=mysqlcfg


Thread (6 messages)

« previous php.bugs (#223379) next »