php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75776 Flushing streams with compression filter is broken
Submitted: 2018-01-08 03:27 UTC Modified: 2021-02-16 18:02 UTC
From: shestero at meta dot ua Assigned: cmb (profile)
Status: Closed Package: Streams related
PHP Version: 7.0.27 OS: Debian
Private report: No CVE-ID: None
 [2018-01-08 03:27 UTC] shestero at meta dot ua
Description:
------------
I used this way to produce compressed output for years but now it return zero-output without any errors anywhere.

Registered Stream Filters:	zlib.*, bzip2.*, convert.iconv.*, mcrypt.*, mdecrypt.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, dechunk

My configure parameters:
'./configure' '--with-openssl' '--with-ssl=/usr/bin/openssl' '--with-ssl-lib=/usr/lib/x86_64-linux-gnu' '--with-libdir=lib/x86_64-linux-gnu' '--with-bz2' '--enable-exif' '--with-gd' '--with-mcrypt' '--with-mysql' '--with-mysql-sock' '--enable-sockets' '--enable-zip' '--with-apxs2=/usr/bin/apxs2' '--with-config-file-path=/var/lib/apache2/conf' '--with-jpeg-dir' '--enable-gd-native-ttf' '--with-xmlrpc' '--with-freetype-dir' '--with-zlib' '--with-zlib-dir' '--enable-maintainer-zts' '--with-tsrm-pthreads' '--with-mysqli' '--enable-mbstring' '--with-pdo-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-curl' '--enable-memcache'

PS Output mute as I adding compression filters. string.toupper and string.tolower work!

Test script:
---------------
error_reporting(E_ALL); ini_set("display_errors", 1);
	if (true)
	{
	  header("Content-Description: File Transfer");
	  header("Content-Disposition: attachment; filename=main.csv.bz2");
	  header("Content-Type: application/x-bzip2");
	  header("Content-Transfer-Encoding: binary");
	}
	else
	{
	  header("Content-Type: application/csv");
	  header("Content-Disposition: attachment;Filename=main.csv");
	}

	$bz = fopen('php://output', 'w');

fwrite($bz,"sdfgdfg"); // output such way
...
fflush($bz); 
fclose($bz);

	stream_filter_append($bz, 'convert.iconv.UTF-8/CP1251//TRANSLIT'); // ok

	if (true)
	{
	  $param = array('blocks' => 6, 'work' => 0); // for bzip2
	  $ok = stream_filter_append($bz, 'bzip2.compress', STREAM_FILTER_WRITE, $param);
	  // $param = array('level' => 6, 'window' => 15, 'memory' => 9); // for gzip
	  //$ok = stream_filter_append($bz, 'zlib.deflate');//, STREAM_FILTER_WRITE, $param);
	  if ($ok===false)
	  {
	    die("Cannot stream_filter_append( 'bzip2.compress' ) !");
	  }
	}

Expected result:
----------------
error or some output as usual

Actual result:
--------------
browser saves zero-size file.

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-01-08 03:30 UTC] shestero at meta dot ua
PS
fwrite($bz,"sdfgdfg"); // output such way
...
fflush($bz); 
fclose($bz);

of cause at the end.
The existing code used about 5-6 years with different PHP versions so I'm quite sure it's ok.
 [2018-01-09 14:37 UTC] mike@php.net
-Status: Open +Status: Verified
 [2018-01-09 14:37 UTC] mike@php.net
Seems to be caused by the fflush() call.
 [2018-01-10 02:08 UTC] shestero at meta dot ua
Yes.
Really commenting fflush solves the problem?

But what's wrong with fflush? I process data streaming and sometimes fill it should be flushed after some portion is over.
 [2018-01-10 02:09 UTC] shestero at meta dot ua
Commenting fflush solves the problem. I checked.
 [2021-02-15 14:08 UTC] cmb@php.net
-Package: *Compression related +Package: Streams related
 [2021-02-15 14:08 UTC] cmb@php.net
With regard to zlib.deflate this is a duplicate of bug #48725,
which is fixed as of PHP 7.4.14 and 8.0.1, respectively, but
apparently bzip2.compress has the same problem.

Recatogorizing as "streams related" since "filter related" is
used too often for ext/filter.
 [2021-02-16 18:02 UTC] cmb@php.net
-Summary: compression filters on stdout not working any more +Summary: Flushing streams with compression filter is broken -Assigned To: +Assigned To: cmb
 [2021-02-16 18:02 UTC] cmb@php.net
While having a closer look at the bzip2 issue, I noticed that the
fix for the other bug does not fully resolve the flushing issue
for zlib compression streams.

Anyhow, this is not particularly related to php://output streams,
but affects streams generally.  Furthermore, not only fflush()
triggers the misbehavior, but also other function calls, such as
rewind(), which flush the stream internally.
 [2021-02-16 18:45 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #75776: Flushing streams with compression filter is broken
On GitHub:  https://github.com/php/php-src/pull/6703
Patch:      https://github.com/php/php-src/pull/6703.patch
 [2021-02-22 14:35 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=963e50c8c48ecfbe7444445e5ca8e33530d630d0
Log: Fix #75776: Flushing streams with compression filter is broken
 [2021-02-22 14:35 UTC] cmb@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 08:01:29 2024 UTC