php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71395 zlib.deflate fails on empty data
Submitted: 2016-01-17 10:22 UTC Modified: 2016-07-02 13:43 UTC
From: salsi at icosaedro dot it Assigned:
Status: Verified Package: Streams related
PHP Version: master-Git-2016-01-17 (Git) OS:
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-01-17 10:22 UTC] salsi at icosaedro dot it
Description:
------------
The zlib.compress filter writes nothing when the data to write are empty. Instead, the DEFLATE algo (RFC 1950) requires to write at least one last block of data, as the gzdeflate() function correctly does:

gzdeflate("") --> "\x03\x00"

The result is that the written file cannot be decoded with gzinflate() withour error. In fact gzinflate() correctly recognizes the empty string as invalid DEFLATE format (there must be at least one block of compressed data with the first but set to mark the last block of data).

The following test code, perfectly working as expected under PHP 5.6.3, fails as stated above on PHP 7.

Test script:
---------------
<?php

/*
 * The zlib.compress filter writes nothing if the data to compress are the empty
 * string.
 * PHP 7.1.0-dev from git 2016-01-17
 */

// Set a safe test environment:
error_reporting(-1);
// maps errors to ErrorException:
function my_error_handler($errno, $message) { throw new ErrorException($message); }
set_error_handler("my_error_handler");

/**
 * @param string $plain
 */
function test($plain) {
	echo "Now testing with $plain:\n";
	$fn = "test";
	$f = fopen($fn, "wb");
	stream_filter_append($f, 'zlib.deflate', STREAM_FILTER_WRITE);
	fwrite($f, $plain);
	fclose($f);
	$compressed = file_get_contents($fn);
	echo "compressed: ", rawurlencode($compressed), "\n";
	$plain2 = gzinflate($compressed);
	echo "decompressed: ", rawurlencode($plain2), "\n";
}

echo "gzdeflate(\"\"): ", rawurlencode(gzdeflate("")), "\n";
test("abc"); // ok
test(""); // no data written, error on gzinflate()
?>

Expected result:
----------------
gzdeflate(""): %03%00
Now testing with abc:
compressed: KLJ%06%00
decompressed: abc
Now testing with :
compressed: %03%00
decompressed:

(this actually is the output of PHP 5.6.3)


Actual result:
--------------
gzdeflate(""): %03%00
Now testing with abc:
compressed: KLJ%06%00
decompressed: abc
Now testing with :
compressed: 
PHP Fatal error:  Uncaught ErrorException: gzinflate(): data error in /home/salsi/src/phplint/bugs/bug-zlib-compress-filter-on-empty-string.php:12


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-03-03 05:01 UTC] salsi at icosaedro dot it
-Summary: zlib.compress fails on empty data +Summary: zlib.deflate fails on empty data
 [2016-03-03 05:01 UTC] salsi at icosaedro dot it
Run into this same issue again. Maybe a shorter test script might help to illustrate how the stream filter works under PHP 5 and fails under PHP 7.1:

<?php
// Deflate stream filter with empty data writes an empty file instead of an empty
// deflate stream on PHP 7.1.
// Works as expected on PHP 5.6.3, same box Slackware 14.1 with zlib v. 1.2.8.
// As stated in http://www.zlib.net, zlib v. 1.2.8 should had solved the bug
// when gzopen() immediately followed by gzclose() would write an empty file.
$fn = "empty.deflated";
$data = "";
$f = fopen($fn, "wb");
stream_filter_append($f, 'zlib.deflate',
	STREAM_FILTER_WRITE,
	array('level' => -1, 'window' => -15, 'memory' => 9) );
fwrite($f, $data);
fclose($f);
echo "gzdeflate():    ", bin2hex(gzdeflate($data)), "\n";
echo "deflate stream: ", bin2hex(file_get_contents($fn)), "\n";
?>

Output of PHP 5.6.3 (cli) (built: Nov 17 2014 20:57:12):
--------------------------------------------------------
gzdeflate():    0300
deflate stream: 0300


Output of PHP 7.1.0-dev (cli) (built: Mar  2 2016 07:50:35) ( NTS ):
--------------------------------------------------------------------
gzdeflate():    0300
deflate stream:
 [2016-07-02 13:43 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2016-07-02 13:43 UTC] cmb@php.net
I can confirm this faulty behavior (tested PHP 7.0.7 on Windows
and a recent head of the PHP 7.0 branch on Linux).

A quick debugging session showed that php_zlib_deflate_filter() is
not called at all, when there are no data.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC