php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48725 Support for flushing in zlib stream
Submitted: 2009-06-29 20:03 UTC Modified: 2020-08-19 10:47 UTC
Votes:25
Avg. Score:4.8 ± 0.6
Reproduced:21 of 21 (100.0%)
Same Version:3 (14.3%)
Same OS:7 (33.3%)
From: slusarz at curecanti dot org Assigned: cmb (profile)
Status: Closed Package: Streams related
PHP Version: 5.2.10 OS: Linux
Private report: No CVE-ID: None
 [2009-06-29 20:03 UTC] slusarz at curecanti dot org
Description:
------------
There does not seem to be any support for flushing data in a zlib compression stream.  Not sure if this is an omission, something obvious that I am missing (and may not be in the documentation), or the fact that the zlib stream filter does not support socket operation.

Reproduce code:
---------------
$stream = stream_socket_client([...]);

// Login to remote server & enable compression remotely (e.g. implementation of IMAP COMPRESS extension - RFC 4978)

stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_WRITE);
stream_set_write_buffer($stream, 0);
fwrite($stream, 'Testing');
fflush($stream);

// tcpdump confirms that nothing is sent from the PHP server to the remote server.  Can confirm that upon socket timeout, the pending data is sent.

// Similarly, compressed data from incoming stream is not available either.
stream_filter_append($stream, 'zlib.inflate', STREAM_FILTER_READ);
$in = fread($stream, 8192);

// fread() on $stream will timeout.


Patches

zlib-filter-flush-fix.patch (last revision 2012-11-02 17:15 UTC by nastasi at alternativeoutput dot it)

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-07-14 03:10 UTC] slusarz at curecanti dot org
<?php

// 16,000 bytes
$text = str_repeat('0123456789abcdef', 1000);

$temp = fopen('php://temp', 'r+');
stream_filter_append($temp, 'zlib.deflate', STREAM_FILTER_WRITE);
fwrite($temp, $text);

rewind($temp);
fpassthru($temp);

print "Location: " . ftell($temp) . "\n";

fclose($temp);

// Expected: compressed data; Location = some non-zero integer
// Actual: No data output; Location = 0
 [2009-10-19 15:15 UTC] jani@php.net
See also bug #49816
 [2009-10-22 21:40 UTC] slusarz at curecanti dot org
I don't think this is related to bug #49816.  Turning off zlib output compression (by adding "ini_set('zlib.output_compression', 'Off');" to the top of the test script)doesn't alter the results from the test script previously reported.
 [2009-10-23 12:25 UTC] jani@php.net
It's related, not same. :)
 [2011-12-13 22:36 UTC] dtrebbien at gmail dot com
See also: http://stackoverflow.com/questions/7508762/using-zlib-filter-with-a-socket-pair/
 [2012-05-20 01:45 UTC] lello-3 at hotmail dot com
Please fix this
 [2012-10-24 13:27 UTC] arnout dot boks at moxio dot com
Verified this with PHP 5.4.7 on Windows.

Another reproduce case:
-----------------------
<?php
$stream = fopen('data://text/plain;base64,' . base64_encode('Foo bar baz'), 
'r');
stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ);
print bin2hex(stream_get_contents($stream));

Expected:
---------
73cbcf57484a2c02e22a00     // == bin2hex(gzdeflate('Foo bar baz'))

Actual:
-------
                           // (empty)

Variations tried:
-----------------
- Replacing the 'zlib.deflate'-filter by another stream filter ('string.rot13') 
gives the correct output.
- Replacing the 'data://'-URL by a 'file://'- or 'http://'-URL pointing to the 
same data gives the correct output.
- Replacing the 'data://'-URL by a 'php://memory' or 'php://temp' stream to 
which the data has been written (and the stream rewinded) gives empty output
 [2012-11-02 17:13 UTC] nastasi at alternativeoutput dot it
I had worked on the php source code and found a fix.

To understand what happens I had traced what happens during a  

    ....
    for ($i = 0 ; $i < 3 ; $i++) {
        fwrite($s[0]);
        fread($s[1]);
        fflush($s[0]);
        fread($s[1]);
        }

loop and I found that the `deflate` function is never called with the `Z_SYNC_FLUSH` flag set because no new data are present into the `backets_in` brigade.  
My fix is to manage the `PSFS_FLAG_FLUSH_INC` case `AND` no iterations are performed on deflate function extending the 

    if (flags & PSFS_FLAG_FLUSH_CLOSE) {

managing `FLUSH_INC` too:

    if (flags & PSFS_FLAG_FLUSH_CLOSE || (flags & PSFS_FLAG_FLUSH_INC && to_be_flushed)) {

All my work is performed on Debian squeeze 6.0.5, and PHP 5.3.3-7+squeeze14 but I already check the current git version and it seems not changed for the essetial parts.
 [2020-08-19 10:47 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: cmb
 [2020-08-19 10:47 UTC] cmb@php.net
The reproducer provided by @arnout doesn't seem to be related,
since it apparently has the same root cause as bug #77069.
 [2020-08-19 16:30 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #48725: Support for flushing in zlib stream
On GitHub:  https://github.com/php/php-src/pull/6019
Patch:      https://github.com/php/php-src/pull/6019.patch
 [2020-12-08 11:25 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=20e75329f2adb11dd231852c061926d0e4080929
Log: Fix #48725: Support for flushing in zlib stream
 [2020-12-08 11:25 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