Bug #71384 [Opn->Csd]: fread() does not detect file access error
| From: | nikic@php.net | Date: | Thu, 25 Jul 2019 09:07:08 +0000 |
| Subject: | Bug #71384 [Opn->Csd]: fread() does not detect file access error | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-221935@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=71384&edit=1
ID: 71384
Updated by: nikic@php.net
Reported by: salsi at icosaedro dot it
Summary: fread() does not detect file access error
-Status: Open
+Status: Closed
Type: Bug
Package: Streams related
Operating System: Slackware 14.1
PHP Version: master-Git-2016-01-15 (Git)
-Assigned To:
+Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
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.
Previous Comments:
------------------------------------------------------------------------
[2017-12-09 11:02:03] salsi at icosaedro dot it
Related To: Bug #71417
------------------------------------------------------------------------
[2017-12-09 10:47:47] salsi at icosaedro dot it
Related To: Bug #71384
------------------------------------------------------------------------
[2017-12-09 10:47:44] salsi at icosaedro dot it
Bug #71384 [Opn]: fread() does not detect file access error
https://bugs.php.net/bug.php?id=71384&edit=2
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"
https://www.mail-archive.com/internals@lists.php.net/msg83033.html
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()
https://bugs.php.net/bug.php?id=39598
+ fread() does not detects decoding errors from filter bzip2.decompress
https://bugs.php.net/bug.php?id=71263
+ fread() does not detect file access error
https://bugs.php.net/bug.php?id=71384
+ fread() does not detect decoding errors from filter zlib.inflate
https://bugs.php.net/bug.php?id=71417
+ require* and include* do not detect input/output error
https://bugs.php.net/bug.php?id=71385
...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()
>
> http://lxr.php.net/xref/PHP_5_6/main/streams/plain_wrapper.c#338
> 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).
------------------------------------------------------------------------
[2017-12-07 17:15:01] ab@php.net
fopen() should have failed in first place, but this check is missing in the php code.
Thanks.
------------------------------------------------------------------------
[2016-01-16 15:14:30] 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.
// https://bugs.php.net/bug.php?id=71384
#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;
}
while(1){
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;
}
}
}
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
// return unbuffered();
// Output:
// read(): -1
// read(): Input/output error
return buffered();
// Output:
// fread(): 0
// fread() : Input / output error
}
<?php
/**
* damaged-disk.php
*
* Investigating https://bugs.php.net/bug.php?id=71384
*
* 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
H4sICI1YmlYAA2RhbWFnZWQtZGlzawDt3TloFGEYgOF/NyvRGE3UeN/3EY3xvo23hSCIkEYb
JUaEEBG1EcF4tRZ29iJiL4iVpa0gdhaCraSx0Cp+k0l01aBIjCvM88CbbJJZ9h+Yb7IzzaYE
FFVz1BWNi+ZFlahUvcGivOahH2e9e9BZTgMDJ/tLg9tdf/Ogc3jT4edNjPqi7VF56PeXbs2+
9urJ8fdP77TdPz+l/e6Y7dAv3DvV9+j25mNLn/c3djx7/KE3W1fj0N+q9+NvKv1+E6iZupTP
fD7/lcF5BYphYMiNePxpACiUplovAKiV4fcB2fXvcP/y/ceH/WnwAmTH2x9fv+67a5H6f7ko
CqPvZnxpr1R+Pv5Lo74Wbhnt4hhzL7LzT/tI579ymlW13fhoQtSQ8vub2X3DSdHkqCnl90en
RFOjaX/w+g+z4+/lSOe/Uuqu2m56NCOaGWXrmh3Nieam/L7t/GhBtDDlt2wXVz332rHTn/9g
SRRIdo5rTKVy29fH5XJbW36Mt6SGcs/Fy1dauy9e7e3Kj/nXdfWls2e6ui/0nKvpuoHRy/+X
fZv/j3X5/AMFUan1AoCaMf9QXOYfisv8Q3GZfygu8w/FZf6huMw/FJf5h+Iy/1Bc5h8AAAAA
AAAAAAAAAAAA/itLoqUnUloW35dHK6KV0apodbQmao3WRuui7KNB1qfBj8xKG6KN0aZoc7Ql
2hpti7ZHO6Kd0a5od7Qn2ht1RPui7KO3DkQHo0PR4ehIdHRM9xgAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDYvgAo
nTthAJABAA==
EOT;
file_put_contents("damaged-disk.img", gzdecode(base64_decode($s)));
?>
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=71384
--
Edit this bug report at https://bugs.php.net/bug.php?id=71384&edit=1