|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71384 fread() does not detect file access error
Submitted: 2016-01-15 23:23 UTC Modified: 2019-07-25 09:07 UTC
From: salsi at icosaedro dot it Assigned: nikic (profile)
Status: Closed Package: Streams related
PHP Version: master-Git-2016-01-15 (Git) OS: Slackware 14.1
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
Solve the problem:
10 - 2 = ?
Subscribe to this entry?

 [2016-01-15 23:23 UTC] salsi at icosaedro dot it
Possibly related: bug #71263 fread() does not detects decoding errors from filter bzip2.decompressed (

Trying to read an unreadable file, fread() does not to detect the problem and simply returns the empty string; no error nor exception whatsover.

The simplest way to simulate an unreadable file on Linux is to read /proc/self/mem, a file that can be succesfully openend but cannot be read from the very beginning (credits for this trick:

	$ cat /proc/self/mem
	cat: /proc/self/mem: Input/output error

A simple test made with gcc C confirms that fopen() succeeds while fread() gives input/output error.

Under PHP, instead, no errors are detected, and fread() simply returns the empty string, as the following test script proves:

Test script:
echo "PHP version: ", PHP_VERSION, "\n";
// set safe test environment:
ini_set("track_errors", "1");

// maps errors to ErrorException:
function my_error_handler($errno, $message) {
	throw new ErrorException($message);

$f = fopen("/proc/self/mem", "r");
do {
	$bytes = fread($f, 1000);
	echo "bytes=";
} while (!feof($f));
// --> bytes=string(0) "", no error whatsoever

echo "Just testing if error detection is still on:\n";
$f = fopen("this file does not exist!", "rb");

Expected result:
PHP version: 7.1.0-dev
(exception on the first fread() telling the file is unreadable)

Actual result:
PHP version: 7.1.0-dev
bytes=string(0) ""
Just testing if error detection is still on:
PHP Fatal error:  Uncaught ErrorException: fopen(this file does not exist!): failed to open stream: No such file or directory in /home/salsi/src/phplint/bug-fread-unreadable-file.php:9
Stack trace:
#0 [internal function]: my_error_handler(2, 'fopen(this file...', '/home/salsi/src...', 23, Array)
#1 /home/salsi/src/phplint/bug-fread-unreadable-file.php(23): fopen('this file does ...', 'rb')
#2 {main}
  thrown in /home/salsi/src/phplint/bug-fread-unreadable-file.php on line 9
Fatal error: Uncaught ErrorException: fopen(this file does not exist!): failed to open stream: No such file or directory in /home/salsi/src/phplint/bug-fread-unreadable-file.php:9
Stack trace:
#0 [internal function]: my_error_handler(2, 'fopen(this file...', '/home/salsi/src...', 23, Array)
#1 /home/salsi/src/phplint/bug-fread-unreadable-file.php(23): fopen('this file does ...', 'rb')
#2 {main}
  thrown in /home/salsi/src/phplint/bug-fread-unreadable-file.php on line 9


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2016-01-16 13:20 UTC]
To increase the likelihood of this being fixed, would it be possible for you to attach the C code that you tested with, to show the exact error conditions.

(I'm not saying that will guarantee that it will be fixed, it just makes it a bit more likely.)
 [2016-01-16 15:14 UTC] salsi at icosaedro dot it
Two sources I used to investigate this issue:

- C test program, compiled with gcc under Slackware 14.1 that show how i/o error is detected reading /proc/self/mem.

- PHP program that generates an ext2 disk image corrupted on pourpose on which i/o error might be tested on, as a further example.


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

int unbuffered() {
	int fd, n;
	char buf[10000];
	fd = open("/proc/self/mem", O_RDONLY);
//	fd = open(__FILE__, O_RDONLY);
	if(fd < 0){
		fprintf(stderr, "open(): %s\n", strerror(errno));
		return EXIT_FAILURE;
	n = read(fd, buf, 100);
	printf("read(): %d\n", n);
	if(n < 0){
		fprintf(stderr, "read(): %s\n", strerror(errno));
		return EXIT_FAILURE;

	return (EXIT_SUCCESS);

int buffered() {
	FILE * f;
	int n;
	char buf[100];
	f = fopen("/proc/self/mem", "r");
//	f = fopen(__FILE__, "r");
	if(f == NULL){
		fprintf(stderr, "fopen(): %s\n", strerror(errno));
		return EXIT_FAILURE;
		n = fread(buf, 1, 100, f);
		printf("fread(): %d\n", n);
		if(n <= 0){
			if( ferror(f) == 0 ){
				return EXIT_SUCCESS;
			} else {
				fprintf(stderr, "fread(): %s\n", strerror(errno));
				return EXIT_FAILURE;


int main(int argc, char** argv) {
//	return unbuffered();
	// Output:
	// read(): -1
	// read(): Input/output error

	return buffered();
	// Output:
	// fread(): 0
	// fread() : Input / output error



 * damaged-disk.php
 * Investigating
 * This program creates the file "damaged-disk.img" containing the damaged
 * disk image of a Linux ext2 partition; the partition contains a single
 * file named "badfile" that can read only partially before I/O error:
 * $ su
 * # mkdir baddisk
 * # mount -r damaged-disk.img baddisk
 * # cat baddisk/badfile
 * cat: baddisk/badfile: Input/output error

$s = <<< EOT

file_put_contents("damaged-disk.img", gzdecode(base64_decode($s)));
 [2017-12-07 17:15 UTC]
fopen() should have failed in first place, but this check is missing in the php code.

 [2017-12-09 10:47 UTC] salsi at icosaedro dot it
Bug #71384 [Opn]: fread() does not detect file access error

Maybe it worth to summarize the general issue emerged from an old thread I started back in 2016-01-21 on the developers' mailing list with subject

"Severe safety fail in file access and stream filters"

There, several bugs related to the I/O layer are listed involving files, sockets and filtered streams, which are still all open:

+ Missing error verification after fwrite()

+ fread() does not detects decoding errors from filter bzip2.decompress

+ fread() does not detect file access error

+ fread() does not detect decoding errors from filter zlib.inflate

+ require* and include* do not detect input/output error

...and maybe much more spread here and there among the libraries, possibly including data base connections and more. Yasuo Ohgaki found that the the origin of the issue has a common denominator, that is errors do not propagate from the libc to the PHP streams interface and get lost with unpredictable results:

> Plain file stream reads data by php_stdiop_read()
> As you can see there is no way to return errors from it. We need
> errno like error handling for PHP streams to propagate errors as well
> as more robust code for unexpected.

Julien Pauli tells there is no a simple fix, and the whole streams library should be re-designed from scratch:

> I think what we should do is sit around the table with people
> interested (Daniel Lowrey may be one of them), and plan a full rewrite
> of streams for PHP next major (PHP 8).
 [2019-07-25 09:07 UTC]
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2019-07-25 09:07 UTC]
This will generate a

fread(): read of 8192 bytes failed with errno=5 Input/output error

notice (promoted to ErrorException in your example) in PHP 7.4.
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Jun 17 17:01:23 2021 UTC