php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39961 fread() trouble with stream wrappers
Submitted: 2006-12-27 11:24 UTC Modified: 2006-12-27 13:47 UTC
From: php_nospam at ramihyn dot sytes dot net Assigned:
Status: Not a bug Package: Streams related
PHP Version: 5.2.0 OS: Win32,Linux x86
Private report: No CVE-ID: None
 [2006-12-27 11:24 UTC] php_nospam at ramihyn dot sytes dot net
Description:
------------
PHP's fread() function reads only the first 8192 bytes of any file accessed via a stream wrapper, even if the file is bigger and the wrappers' stream_eof() method returns false to signal it is NOT the end of the file.

I expect fread() to repeat calling the wrappers' stream_read()  and stream_eof() methods until stream_eof() signals the end of file or stream_read() returns less than the requested 8192 bytes.

I encountered this behaviour with PHP 5.2.0 on Win32 and Linux x86.

Reproduce code:
---------------
<?

class PHP_Bug {
	private $data; private $pos;
	function initializeStream()
	{
		$this->data = str_repeat("-",16399);
		$this->pos = 0;
	}
	function stream_open($fn)
	{
		$this->initializeStream();
		return true;
	}
	function stream_stat()
	{
		$this->initializeStream();
		return array(0,0,0100444,"mode"=>0100444,"size"=>strlen($this->data));
	}
	function url_stat()
	{
		return $this->stream_stat();
	}
	function stream_read($cnt)
	{
		echo __METHOD__."(".$cnt.")\n";
		$ret = substr($this->data,$this->pos,$cnt);
		$this->pos += strlen($ret);
		return $ret;
	}
	function stream_eof()
	{
		$ret = ($this->pos >= strlen($this->data));
		echo __METHOD__."=".(($ret)?"true":"false")."\n";
		return $ret;
	}
}

stream_wrapper_register("bug","PHP_Bug");

$fs = filesize("bug://");
$fp = fopen("bug://","r");
$ret = fread($fp,$fs);
fclose($fp);
echo "size is ".strlen($ret)."\n";

?>

Expected result:
----------------
PHP_Bug::stream_read(8192)
PHP_Bug::stream_eof=false
PHP_Bug::stream_read(8192)
PHP_Bug::stream_eof=false
PHP_Bug::stream_read(8192)
PHP_Bug::stream_eof=true
size is 16399

Actual result:
--------------
PHP_Bug::stream_read(8192)
PHP_Bug::stream_eof=false
size is 8192


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-12-27 11:35 UTC] tony2001@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

http://php.net/fread
 [2006-12-27 11:58 UTC] php_nospam at ramihyn dot sytes dot net
Thanks for marking this bug as "bogus". Would you please tell me, where this behaviour is documented? I cant find it.

Think of it what you want, but this is not bogus. In my example script, there are 16399 bytes to read. fread() was told to read 16399 bytes. fread() calls the stream wrappers' stream_read() method only once, which only reads 8192 bytes.
 [2006-12-27 12:04 UTC] php_nospam at ramihyn dot sytes dot net
In fact, it looks like the return value of stream_eof() is ignored.
 [2006-12-27 13:47 UTC] php_nospam at ramihyn dot sytes dot net
As a work-around, stream_copy_to_stream() can be used, which produces the expected result, but how would it be possible to copy the file content to a string variable using stream_copy_to_stream()?

I guess it is the 3 lines of code in _php_stream_read() found in the ZEND API, which breaks the loop to avoid greedy read. What is that piece of code useful for, except for breaking fread()?

I recommend to change the documentation for fread() to clarify it should be used with 8192 byte blocks at max to ensure it works as expected, which isnt stated at least in the german documentation.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC