php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #69163 fopen(__DIR__, 'r') succeeds
Submitted: 2015-03-02 19:16 UTC Modified: 2016-10-12 16:04 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: salsi at icosaedro dot it Assigned:
Status: Open Package: Streams related
PHP Version: Irrelevant OS: Linux
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:

 

 [2015-03-02 19:16 UTC] salsi at icosaedro dot it
Description:
------------
On Linux, opening a directory succeeds; subsequent reads always returns string("") and feof() is true, no warnings.


Test script:
---------------
<?php
error_reporting(PHP_INT_MAX);
$f = fopen(__FILE__, 'r');
var_dump($f);
for($i=0; $i<3; $i++){
	echo "feof is "; var_dump(feof($f));
	echo "fread returns "; var_dump(fread($f, 10));
}


Actual output:
----------------------------------
resource(5) of type (stream)                                                                         
feof is bool(false)                                                                                  
fread returns string(10) "<?php                                                                      
erro"                                                                                                
feof is bool(false)                                                                                  
fread returns string(10) "r_reportin"                                                                
feof is bool(false)                                                                                  
fread returns string(10) "g(PHP_INT_"  

Expected result:
----------------
Expected output:
-----------------------------------
E_WARNING: cannot open directory
boolean(false)
...


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-03-02 20:22 UTC] salsi at icosaedro dot it
ERRATA/CORRIGE. In my test script, the line

    $f = fopen(__FILE__, 'r');

should contain a directory, for example:

    $f = fopen(__DIR__, 'r');
    $f = fopen('.', 'r');
    $f = fopen('..', 'r');

Thanks to Richard Gray for signaling this bug in my report.

ADDENDUM. Under Windows Vista fopen() fails on a directory, as it should.
 [2015-03-04 01:05 UTC] danack@php.net
-Status: Open +Status: Feedback
 [2015-03-04 01:05 UTC] danack@php.net
"A Linux system, just like UNIX, makes no difference between a file and a directory, since a directory is just a file containing names of other files."

From the manual:

Note: This function may also succeed when filename is a directory. If you are unsure whether filename is a file or a directory, you may need to use the is_dir() function before calling fopen().

Are you sure this actually should be treated as a bug?
 [2015-03-05 09:25 UTC] salsi at icosaedro dot it
-Status: Feedback +Status: Open
 [2015-03-05 09:25 UTC] salsi at icosaedro dot it
Currently the libc fopen() function under Linux (and probably under any Unix-like OS) succeeds by opening a directory for reading, although nothing can be read and the EOF condition is immediately set. This is a legacy, very old behavior of the unices a modern application language as PHP is should not comply with anymore.

Under Windows the same attempt immediately fails.

My proposal is to make the PHP fopen() function behave in more consistent, cross-OS uniform and safer way by rejecting such an attempt atomically from inside PHP itself using a C code similar to this one, that detects the actual type of the opened file:

    FILE * f;
    struct stat fileinfo;

    //f = fopen(__FILE__, "r"); // works
    f = fopen("/", "r"); // --> displays "Ia a directory (PHP specific restriction)”
    //f = fopen("/root", "r"); // displays "Permission denied"
    //f = fopen("/dev/sda5", "r"); // displays "Permission denied"
    if( f == NULL ){
        printf("%s\n", strerror(errno));
        return 1;
    }
    if( fstat(fileno(f), &fileinfo) < 0 ){
        printf("%s\n", strerror(errno));
        return 1;
    }
    if( S_ISDIR(fileinfo.st_mode) ){
        printf("Ia a directory (PHP specific restriction)");
        return 1;
    }
    // OK

In this way the manual page becomes simpler by removing ambiguous warnings and suggestions nobody applies anyway (never seen is_dir() after fopen() in a PHP program).

Opening a directory for writing already gives error, so there is nothing to fix here:

    $f = fopen("/", "w");
    –-> E_WARNING: fopen(/): failed to open stream: Is a directory

Changed "Bug Type" from "Bug" to "Feature/Change request", which seems more appropriate.
 [2016-10-12 16:04 UTC] cmb@php.net
-Type: Bug +Type: Feature/Change Request
 [2016-10-12 16:04 UTC] cmb@php.net
> Changed "Bug Type" from "Bug" to "Feature/Change request", […]

… and after previewing the comment, the bug tracker did reset to
"bug" again – annoying bug.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 07 17:01:27 2024 UTC