php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #34071 buffering is destroyed when using ob_gzhandler and ob_clean
Submitted: 2005-08-10 18:08 UTC Modified: 2005-08-19 01:00 UTC
Votes:19
Avg. Score:3.9 ± 1.2
Reproduced:17 of 17 (100.0%)
Same Version:3 (17.6%)
Same OS:5 (29.4%)
From: dennis at nocertainty dot com Assigned:
Status: No Feedback Package: Output Control
PHP Version: 5CVS-2005-08-10 (dev) OS: Windows XP SP2
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
32 + 22 = ?
Subscribe to this entry?

 
 [2005-08-10 18:08 UTC] dennis at nocertainty dot com
Description:
------------
When using ob_start('ob_gzhandler') and ob_clean() the output buffer is destroyed, and no ob_* function works anymore. It seems that PHP4 had this problem as well (http://bugs.php.net/bug.php?id=29125)

Reproduce code:
---------------
<?php
ob_start('ob_gzhandler');

echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

Expected result:
----------------
"Should be shown" should've been printed, instead nothing is returned, and nothing displays anymore.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-08-10 18:14 UTC] tony2001@php.net
Can't reproduce.
Please try with PHP CLI and tell what SAPI you're using. 
 [2005-08-10 18:19 UTC] dennis at nocertainty dot com
It works with PHP CLI.

SAPI: cgi-fcgi
 [2005-08-10 18:39 UTC] tony2001@php.net
Still can't reproduce, even with FCGI.
Does this work for you:
<?php
function foo($data) {
	return $data;
}
ob_start('foo');
echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>
?
 [2005-08-10 18:50 UTC] dennis at nocertainty dot com
Yes, that works. But as soon as I use ob_gzhandler, instead of foo, nothing is displayed.

I run PHP4 and PHP5 at the same time (port 80 is PHP4.3.4, port 83 is PHP5Dev). Could it be that the bug is caused by my PHP4 installation?
 [2005-08-10 18:56 UTC] tony2001@php.net
Are you sure there is nothing shown in the "View Source" tab?
I'm almost sure your browser just hides binary output from you. So try this:
telnet localhost 80
GET /script.php HTTP/1.0
<Enter>
<Enter>

 [2005-08-10 19:03 UTC] dennis at nocertainty dot com
You're right, that works, and I get the correct result.
 [2005-08-10 19:20 UTC] rasmus@php.net
That's not a very good test since ob_gzhandler checks the request's accept-encoding and since your telnet test didn't specify that you could accept gzip or deflate, then the gzhandler simply didn't do anything.
 [2005-08-10 19:21 UTC] tony2001@php.net
Not PHP problem then.
 [2005-08-10 19:44 UTC] dennis at nocertainty dot com
Rasmus is right. The telnet thing works because ob_gzhandler doesn't do anything. As soon as a specify a Content-Encoding: gzip header, nothing gets displayed again. So it's not my browser that's causing the problem.
 [2005-08-10 19:47 UTC] dennis at nocertainty dot com
Also, I disabled PHP4 in my http.conf file, and it still doesn't work properly in PHP5Dev. So I still believe there's a bug in PHP5.
 [2005-08-10 20:12 UTC] tony2001@php.net
Then provide more info about it; look into the apache logs; try on another server and with another PHP version etc etc.
As I've already said, it works perfectly here.
 [2005-08-11 20:54 UTC] dennis at nocertainty dot com
I found someone else who has the same problem as me:
http://www.sitepoint.com/forums/showpost.php?p=2093119&postcount=5

However, I can't find any specific information. I looked through my Apache error log, and the only thing I found was:

[Wed Aug 10 18:59:56 2005] [error] [client 127.0.0.1] request failed: erroneous characters after protocol string: \\xff\\xfb\\x1f\\xff\\xfb \\xff\\xfb\\x18\\xff\\xfb'\\xff\\xfd\\x01\\xff\\xfb\\x03\\xff\\xfd\\x03GET /gzip2.php HTTP/1.0
[Wed Aug 10 19:00:21 2005] [error] [client 127.0.0.1] request failed: erroneous characters after protocol string: \\xff\\xfb\\x1f\\xff\\xfb \\xff\\xfb\\x18\\xff\\xfb'\\xff\\xfd\\x01\\xff\\xfb\\x03\\xff\\xfd\\x03GET /gzip2.php HTTP/1.0

But I'm not sure if that's entirely relevant. But there's nothing more that's related to it.
 [2005-08-11 23:12 UTC] sniper@php.net
1) Check your php.ini settings (how they differ to whatever you used as base for your php.ini, -dist or -recommended)
2) Set error_reporting to E_ALL and try again..

 [2005-08-14 23:10 UTC] dehstil at gmail dot com
I've reproduced the bug. I've been wondering why my script wouldn't run until I saw this bug.  I'm using apache server on win xp with php 4 as a module.

The above code produced the bug:
<?php
ob_start('ob_gzhandler');
echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

With further debuging this doesn't work either:
<?php
function handler($buffer,$mode){
$buffer=ob_gzhandler($buffer,$mode);
return $buffer;
}
ob_start('handler');

echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

I noticed that the content-length in my headers was non-zero so I tried this and lo and behold:
<?php
function handler($buffer,$mode){
$buffer=ob_gzhandler($buffer,$mode);
header('Content-Encoding:');
header('Content-Type: text/plain');
header('Vary:');
return bin2hex($buffer);
}
ob_start('handler');
echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

I realized the bug is sending bad gz binary but for some reason the following code did work...:
<?php
function handler($buffer,$mode){
$buffer=ob_gzhandler($buffer,$mode);
header('Content-Encoding:');
header('Content-Type: text/plain');
header('Vary:');
return gzuncompress($buffer);
}

ob_start('handler');
echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

To my surprise, this didn't, thus confusing me:
<?php
function handler($buffer,$mode){
$buffer=ob_gzhandler($buffer,$mode);
header('Content-Encoding:');
header('Content-Type: text/plain');
header('Vary:');
return 'test'.gzuncompress($buffer);
}

ob_start('handler');

echo 'Should NOT be shown';
ob_clean();
echo 'Should be shown';
?>

I'll be looking for the source on cvs and report back to ya!
 [2005-08-19 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".
 [2006-01-27 16:32 UTC] greg at xdissent dot com
this appears to be ob_gzhandler's fault.  it seems to send the content-encoding: gzip header even if ob_end_clean or similar is called which produces no output.  that means that if you use ob_gzhandler and then change your mind about compression and need to kill that buffer, you're out of luck. in the following small example, "output" WILL be printed in plaintext but will be misinterpreted by the browser as gzipped content.

<?php
ob_start("ob_gzhandler");
echo("trashed");
ob_end_clean();
echo("output");
?>

you can use telnet to better view the situation because it will almost always result in a white browser window.  as others have pointed out, you have to use the accept-encoding to trigger ob_gzhandler's compression:

$ telnet localhost 80
GET /ob_test.php HTTP/1.1
Host: localhost
Accept-Encoding: gzip,deflate

now, should ob_gzhandler really be sending the header if the buffer is ended without outputting anything?  should it maybe check the length of the buffer when it is closed to determine whether or not the content-encoding header should be sent?
 [2011-04-16 17:38 UTC] arvenil at klecza dot pl
You can't change your mind about compression in half way however you can still kill that buffer and send other.

<?php
ob_start("ob_gzhandler");
echo("trashed");
ob_end_clean();
ob_start("ob_gzhandler");
echo("output");
ob_end_flush();
?>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 15:01:29 2024 UTC