php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71263 fread() does not report bzip2.decompress errors
Submitted: 2016-01-02 16:01 UTC Modified: 2020-04-17 13:39 UTC
From: salsi at icosaedro dot it Assigned: cmb (profile)
Status: Closed Package: Streams related
PHP Version: Irrelevant OS: Slackware 14.1
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: salsi at icosaedro dot it
New email:
PHP Version: OS:

 

 [2016-01-02 16:01 UTC] salsi at icosaedro dot it
Description:
------------
When the bzip2.decompress filter is applied to a stream, the fread() function does not detect decoding errors on a corrupted file and keeps instead returning the empty string or garbage. The following script illustrates 3 distinct cases.

Checking what really happens inside the php_bz2_decompress_filter() function, in 2 of the 3 cases this function correctly detects an error in the corrupted file and returns PSFS_ERR_FATAL, but in the script the fread() function always succeeds.

In one case the php_bz2_decompress_filter() function does not detect anything, but fread() succeeds and returns the empty string.

In my opinion, if a decoding error is detected it is just like reading from a damaged file and fread() should return FALSE and triggering E_WARNING (which this script would map to ErrorException).

I've tested on PHP 7.0-dev, but I don't think the PHP version does really matters here.

Unsure if this bug is in some way related to #17651.


Test script:
---------------
<?php
// Bug report: bzip2.decompress fails to detect corrupted data.

// Set a safe environment:
error_reporting(-1);
ini_set("track_errors", "1");

/**
 * Maps errors to ErrorException.
 * @access private
 * @param int $errno
 * @param string $message
 * @return boolean
 * @throws ErrorException
 */
function my_error_handler($errno, $message /*, $filename, $lineno, $context */)
{
	throw new ErrorException($message); 
}

set_error_handler("my_error_handler");


/**
 * Testing reading corrupted BZIP2 file using bzip2.decompress filter.
 * @throws ErrorException
 */
function main()
{
	$plain = "The quick brown fox jumps over the lazy dog.";
	$fn = "test.bz2";
	$compressed = (string) bzcompress($plain);
	echo "Compressed len = ", strlen($compressed), "\n";
	
	// Set a random byte in the middle of the compressed data
	// --> php_bz2_decompress_filter() detects fatal error
	// --> fread() displays empty string then garbage, no errors detected:
	$compressed[strlen($compressed) - 15] = 'X';
	
	// Truncate the compressed data
	// --> php_bz2_decompress_filter() does not detect errors,
	// --> fread() displays the empty string:
//	$compressed = substr($compressed, 0, strlen($compressed) - 20);
	
	// Corrupted final CRC
	// --> php_bz2_decompress_filter() detects fatal error
	// --> fread() displays an empty string, then the correct plain text, no error detected:
//	$compressed[strlen($compressed)-2] = 'X';

	file_put_contents($fn, $compressed);
	
	$r = fopen($fn, "r");
	stream_filter_append($r, 'bzip2.decompress', STREAM_FILTER_READ);
	while( ! feof($r) ){
		$s = fread($r, 100);
		echo "read: "; var_dump($s);
	}
	fclose($r);
	unlink($fn);
}

main();
?>

Expected result:
----------------
Compressed len = 81
Fatal error: Uncaught ErrorException: fread() I/O error in /home/salsi/BZIP2-bug-report.php:24

(or possibly a more descriptive error message, although it might be difficult to do due to the limitations of the filter interface)

Actual result:
--------------
Compressed len = 81
read: string(0) ""
read: string(43) "bthes ohe rpujumr.bthes ohe rpujumr.bthes o"


Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-01-16 00:27 UTC] salsi at icosaedro dot it
Possibly related:

1. require* and include* do not detect input/output error
   https://bugs.php.net/bug.php?id=71385

2. fread() does not detect file access error
   https://bugs.php.net/bug.php?id=71384

In all these case it seems I/O errors fails to propagate through the chain of the stream functions, either returning empty string or garbage, with severe safety and security risks both for front-end and back-end processes.
 [2018-08-20 17:37 UTC] cmb@php.net
-Package: Filter related +Package: Streams related
 [2020-04-17 08:35 UTC] cmb@php.net
-Summary: fread() does not detects decoding errors from filter bzip2.decompress +Summary: fread() does not report bzip2.decompress errors
 [2020-04-17 08:35 UTC] cmb@php.net
As of PHP 7.4.0, bzip2.decompress errors already cause fread() to
return false, due to a more general fix of the stream behavior[1].
This is still a silent failure, though.

[1] <https://www.php.net/manual/en/migration74.incompatible.php#migration74.incompatible.core.fread-fwrite>
 [2020-04-17 12:13 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #71263: fread() does not report bzip2.decompress errors
On GitHub:  https://github.com/php/php-src/pull/5406
Patch:      https://github.com/php/php-src/pull/5406.patch
 [2020-04-17 13:37 UTC] cmb@php.net
-Summary: fread() does not report bzip2.decompress errors +Summary: fread() does not report decompression errors -Status: Open +Status: Verified -Assigned To: +Assigned To: cmb
 [2020-04-17 13:37 UTC] cmb@php.net
The zlib.inflate filter has the same issue.
 [2020-04-17 13:39 UTC] cmb@php.net
-Summary: fread() does not report decompression errors +Summary: fread() does not report bzip2.decompress errors
 [2020-04-17 13:39 UTC] cmb@php.net
> The zlib.inflate filter has the same issue.

But that has already reported as bug #71417.
 [2020-04-20 12:22 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d757be640f5105b8542b781ce93804af494229a8
Log: Fix #71263: fread() does not report bzip2.decompress errors
 [2020-04-20 12:22 UTC] cmb@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC