php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45149 Handling plus sign in an url failed
Submitted: 2008-06-02 14:19 UTC Modified: 2010-02-26 03:56 UTC
Votes:11
Avg. Score:4.9 ± 0.3
Reproduced:10 of 11 (90.9%)
Same Version:6 (60.0%)
Same OS:9 (90.0%)
From: frode dot langvik at exense dot com Assigned:
Status: Wont fix Package: Strings related
PHP Version: 5.2.6 OS: *
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2008-06-02 14:19 UTC] frode dot langvik at exense dot com
Description:
------------
When sending parameters in an url, the way of handling plus signs have changed. In PHP 4.3.9 everything worked fine, but after upgrading to version 5.2.6 it fails. In the test case will function base64_encode() generate a plus sign in both php version 4.3.9 and 5.2.5, but in version 5.2.5 it seems that the url is broken and base64_decode() got wrong value to work with. The test case includes some norwegian characters, but I have also discovered it when using other characters.

Reproduce code:
---------------
<?php

	if ($_GET['args'])
	{
		echo 'Result: '.unserialize(base64_decode($_GET['args']));
	}

	echo '<br><a href="encode.php?args='.base64_encode(serialize('???')).'">Test link</a>';

?>

Expected result:
----------------
Result: ???

Actual result:
--------------
Result:

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-10-26 23:12 UTC] jani@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2008-11-03 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2008-11-10 21:04 UTC] phpbugs at samrowe dot com
I'm seeing this behavior on RHEL5's PHP-5.1.6-20.el5_2.1 when trying to use JSON data-structures containing strings that contain '+'.
 [2010-02-26 02:40 UTC] mat at ucsc dot edu
We are seeing this issue with base64_encode and base64_decode.

We have php 5.2.6 and the url string contains a '+' sign in the url parameter, however, in php itself if we $_GET the same parameter the + is replaced by a space.  The base64_decode cannot use this value in php 5.2.6.

However, 5.0.4 (my other running reference) base64_decode can read the blank.  So the blank may be okay except that base64_decode seems to have changed in the newer version.

Here is a test:

The url parameter is (has +):
YTozMDp7czo0OiJTVFJNIjtzOjQ6IjIxMDIiO3M6OToiQ0xBU1NfTkJSIjtzOjU6IjcyNTczIjtzOjEzOiJDTEFTU19TRUNUSU9OIjtzOjI6IjAxIjtzOjEzOiJDTEFTU19NVEdfTkJSIjtzOjE6IjEiO3M6MTI6IlNFU1NJT05fQ09ERSI7czoxOiIxIjtzOjEwOiJDTEFTU19TVEFUIjtzOjE6IkEiO3M6NzoiU1VCSkVDVCI7czo0OiJCSU9FIjtzOjExOiJDQVRBTE9HX05CUiI7czo0OiIgMTA3IjtzOjU6IkRFU0NSIjtzOjc6IkVjb2xvZ3kiO3M6MTM6IlNTUl9DT01QT05FTlQiO3M6MzoiTEVDIjtzOjEwOiJTVEFSVF9USU1FIjtzOjc6IjAyOjAwUE0iO3M6ODoiRU5EX1RJTUUiO3M6NzoiMDM6NDVQTSI7czo5OiJGQUNfREVTQ1IiO3M6MTQ6IkVpZ2h0IEFjYWQgMjQwIjtzOjM6Ik1PTiI7czoxOiJOIjtzOjQ6IlRVRVMiO3M6MToiWSI7czozOiJXRUQiO3M6MToiTiI7czo1OiJUSFVSUyI7czoxOiJZIjtzOjM6IkZSSSI7czoxOiJOIjtzOjM6IlNBVCI7czoxOiJOIjtzOjM6IlNVTiI7czoxOiJOIjtzOjk6IkVOUkxfU1RBVCI7czoxOiJPIjtzOjg6IldBSVRfVE9UIjtzOjE6IjAiO3M6ODoiRU5STF9DQVAiO3M6MjoiNzYiO3M6ODoiRU5STF9UT1QiO3M6MToiMCI7czo5OiJMQVNUX05BTUUiO3M6NToiTW9vcmUiO3M6MTA6IkZJUlNUX05BTUUiO3M6ODoiSm9uYXRoYW4iO3M6MTE6Ik1JRERMRV9OQU1FIjtzOjE6IlciO3M6MTY6IkNPTUJJTkVEX1NFQ1RJT04iO3M6MToiICI7czo1OiJUT1BJQyI7TjtzOjEyOiJESVNQTEFZX05BTUUiO3M6MjQ6IkVzdGVzLEouQS48YnI+TW9vcmUsSi5XLiI7fQ==

The $_GET value of this data dropps the + to look like this (in case text wrap breaks on my space it is a space at column 1036):
YTozMDp7czo0OiJTVFJNIjtzOjQ6IjIxMDIiO3M6OToiQ0xBU1NfTkJSIjtzOjU6IjcyNTczIjtzOjEzOiJDTEFTU19TRUNUSU9OIjtzOjI6IjAxIjtzOjEzOiJDTEFTU19NVEdfTkJSIjtzOjE6IjEiO3M6MTI6IlNFU1NJT05fQ09ERSI7czoxOiIxIjtzOjEwOiJDTEFTU19TVEFUIjtzOjE6IkEiO3M6NzoiU1VCSkVDVCI7czo0OiJCSU9FIjtzOjExOiJDQVRBTE9HX05CUiI7czo0OiIgMTA3IjtzOjU6IkRFU0NSIjtzOjc6IkVjb2xvZ3kiO3M6MTM6IlNTUl9DT01QT05FTlQiO3M6MzoiTEVDIjtzOjEwOiJTVEFSVF9USU1FIjtzOjc6IjAyOjAwUE0iO3M6ODoiRU5EX1RJTUUiO3M6NzoiMDM6NDVQTSI7czo5OiJGQUNfREVTQ1IiO3M6MTQ6IkVpZ2h0IEFjYWQgMjQwIjtzOjM6Ik1PTiI7czoxOiJOIjtzOjQ6IlRVRVMiO3M6MToiWSI7czozOiJXRUQiO3M6MToiTiI7czo1OiJUSFVSUyI7czoxOiJZIjtzOjM6IkZSSSI7czoxOiJOIjtzOjM6IlNBVCI7czoxOiJOIjtzOjM6IlNVTiI7czoxOiJOIjtzOjk6IkVOUkxfU1RBVCI7czoxOiJPIjtzOjg6IldBSVRfVE9UIjtzOjE6IjAiO3M6ODoiRU5STF9DQVAiO3M6MjoiNzYiO3M6ODoiRU5STF9UT1QiO3M6MToiMCI7czo5OiJMQVNUX05BTUUiO3M6NToiTW9vcmUiO3M6MTA6IkZJUlNUX05BTUUiO3M6ODoiSm9uYXRoYW4iO3M6MTE6Ik1JRERMRV9OQU1FIjtzOjE6IlciO3M6MTY6IkNPTUJJTkVEX1NFQ1RJT04iO3M6MToiICI7czo1OiJUT1BJQyI7TjtzOjEyOiJESVNQTEFZX05BTUUiO3M6MjQ6IkVzdGVzLEouQS48YnI TW9vcmUsSi5XLiI7fQ==


Using a bit of php one can try the base64_decode on both strings.  It will produce data with the +, but not with the space (5.2.6).  Here is the test case code with a space (be careful text will line break on the space in some editors):

<?php //$Header: /opt/app/cvs/pisa/cs9/tst/sr9_2013/soc_detail.php,v 1.28 2009/10/28 21:52:44 pisa Exp $

$classdata = 'YTozMDp7czo0OiJTVFJNIjtzOjQ6IjIxMDIiO3M6OToiQ0xBU1NfTkJSIjtzOjU6IjcyNTczIjtzOjEzOiJDTEFTU19TRUNUSU9OIjtzOjI6IjAxIjtzOjEzOiJDTEFTU19NVEdfTkJSIjtzOjE6IjEiO3M6MTI6IlNFU1NJT05fQ09ERSI7czoxOiIxIjtzOjEwOiJDTEFTU19TVEFUIjtzOjE6IkEiO3M6NzoiU1VCSkVDVCI7czo0OiJCSU9FIjtzOjExOiJDQVRBTE9HX05CUiI7czo0OiIgMTA3IjtzOjU6IkRFU0NSIjtzOjc6IkVjb2xvZ3kiO3M6MTM6IlNTUl9DT01QT05FTlQiO3M6MzoiTEVDIjtzOjEwOiJTVEFSVF9USU1FIjtzOjc6IjAyOjAwUE0iO3M6ODoiRU5EX1RJTUUiO3M6NzoiMDM6NDVQTSI7czo5OiJGQUNfREVTQ1IiO3M6MTQ6IkVpZ2h0IEFjYWQgMjQwIjtzOjM6Ik1PTiI7czoxOiJOIjtzOjQ6IlRVRVMiO3M6MToiWSI7czozOiJXRUQiO3M6MToiTiI7czo1OiJUSFVSUyI7czoxOiJZIjtzOjM6IkZSSSI7czoxOiJOIjtzOjM6IlNBVCI7czoxOiJOIjtzOjM6IlNVTiI7czoxOiJOIjtzOjk6IkVOUkxfU1RBVCI7czoxOiJPIjtzOjg6IldBSVRfVE9UIjtzOjE6IjAiO3M6ODoiRU5STF9DQVAiO3M6MjoiNzYiO3M6ODoiRU5STF9UT1QiO3M6MToiMCI7czo5OiJMQVNUX05BTUUiO3M6NToiTW9vcmUiO3M6MTA6IkZJUlNUX05BTUUiO3M6ODoiSm9uYXRoYW4iO3M6MTE6Ik1JRERMRV9OQU1FIjtzOjE6IlciO3M6MTY6IkNPTUJJTkVEX1NFQ1RJT04iO3M6MToiICI7czo1OiJUT1BJQyI7TjtzOjEyOiJESVNQTEFZX05BTUUiO3M6MjQ6IkVzdGVzLEouQS48YnI TW9vcmUsSi5XLiI7fQ==';
        $class_result = base64_decode($classdata);
echo "<br/>After calling base64_decode ... <br/>";
echo '<pre>';
print_r($class_result);
echo '</pre>';
        $class_result = unserialize($class_result);
echo "<br/>After unserialized ... <br/>";
echo '<pre>';
print_r($class_result);

        echo "<br/>Start print class_resul ....<pre>";
        print_r($class_result);
        echo "</pre><br/>*****<br/>";
?>



Here is code with the + in the string:

<?php //$Header: /opt/app/cvs/pisa/cs9/tst/sr9_2013/soc_detail.php,v 1.28 2009/10/28 21:52:44 pisa Exp $

$classdata = 'YTozMDp7czo0OiJTVFJNIjtzOjQ6IjIxMDIiO3M6OToiQ0xBU1NfTkJSIjtzOjU6IjcyNTczIjtzOjEzOiJDTEFTU19TRUNUSU9OIjtzOjI6IjAxIjtzOjEzOiJDTEFTU19NVEdfTkJSIjtzOjE6IjEiO3M6MTI6IlNFU1NJT05fQ09ERSI7czoxOiIxIjtzOjEwOiJDTEFTU19TVEFUIjtzOjE6IkEiO3M6NzoiU1VCSkVDVCI7czo0OiJCSU9FIjtzOjExOiJDQVRBTE9HX05CUiI7czo0OiIgMTA3IjtzOjU6IkRFU0NSIjtzOjc6IkVjb2xvZ3kiO3M6MTM6IlNTUl9DT01QT05FTlQiO3M6MzoiTEVDIjtzOjEwOiJTVEFSVF9USU1FIjtzOjc6IjAyOjAwUE0iO3M6ODoiRU5EX1RJTUUiO3M6NzoiMDM6NDVQTSI7czo5OiJGQUNfREVTQ1IiO3M6MTQ6IkVpZ2h0IEFjYWQgMjQwIjtzOjM6Ik1PTiI7czoxOiJOIjtzOjQ6IlRVRVMiO3M6MToiWSI7czozOiJXRUQiO3M6MToiTiI7czo1OiJUSFVSUyI7czoxOiJZIjtzOjM6IkZSSSI7czoxOiJOIjtzOjM6IlNBVCI7czoxOiJOIjtzOjM6IlNVTiI7czoxOiJOIjtzOjk6IkVOUkxfU1RBVCI7czoxOiJPIjtzOjg6IldBSVRfVE9UIjtzOjE6IjAiO3M6ODoiRU5STF9DQVAiO3M6MjoiNzYiO3M6ODoiRU5STF9UT1QiO3M6MToiMCI7czo5OiJMQVNUX05BTUUiO3M6NToiTW9vcmUiO3M6MTA6IkZJUlNUX05BTUUiO3M6ODoiSm9uYXRoYW4iO3M6MTE6Ik1JRERMRV9OQU1FIjtzOjE6IlciO3M6MTY6IkNPTUJJTkVEX1NFQ1RJT04iO3M6MToiICI7czo1OiJUT1BJQyI7TjtzOjEyOiJESVNQTEFZX05BTUUiO3M6MjQ6IkVzdGVzLEouQS48YnI+TW9vcmUsSi5XLiI7fQ==';
        $class_result = base64_decode($classdata);
echo "<br/>After calling base64_decode ... <br/>";
echo '<pre>';
print_r($class_result);
echo '</pre>';
        $class_result = unserialize($class_result);
echo "<br/>After unserialized ... <br/>";
echo '<pre>';
print_r($class_result);

        echo "<br/>Start print class_resul ....<pre>";
        print_r($class_result);
        echo "</pre><br/>*****<br/>";
?>


This will dump an array course data I generated.  The only difference is the space or +.  In 5.0.4 it works with a space.  The space is not there in the URL in 5.2.6, but is after a $_GET on the parameter.
 [2010-02-26 03:53 UTC] aharvey@php.net
This was changed by the fix for bug #34214 (revision 194419, just in 
case anyone's morbidly interested).

Frankly, this is a classic case of "damned if you do, damned if you 
don't": the "new" behaviour (which has actually been in place since PHP 
5.1.0, so since November 2005 in a stable release) is compliant with 
the spec, while the "old" behaviour was more useful for software that 
doesn't properly URL encode base64 values in GET variables.

Given that you can't really have this both ways and PHP 5 has had the 
"new" behaviour for more than four years, I doubt we'd change this back 
now. The real lesson in this is that you do need to urlencode() or 
rawurlencode() base64 data in URLs, since + characters do have a 
special meaning there.
 [2010-02-26 03:56 UTC] rasmus@php.net
Yes, just to echo the previous comment.  base64-encoding is not safe 
for URLs.  That's why Flickr and other sites use base58-encoding to 
generate unique tokens for their URLs.  You will need to urlencode your 
base64-encoded strings.  Even if we hacked it in PHP, it would break 
other places.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Jul 24 06:01:27 2019 UTC