Bug #69163 [Fbk->Opn]: fopen(__DIR__, 'r') succeeds

From: Date: Thu, 05 Mar 2015 09:25:16 +0000
Subject: Bug #69163 [Fbk->Opn]: fopen(__DIR__, 'r') succeeds
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-191184@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69163&edit=1

 ID:                 69163
 User updated by:    salsi at icosaedro dot it
 Reported by:        salsi at icosaedro dot it
 Summary:            fopen(__DIR__, 'r') succeeds
-Status:             Feedback
+Status:             Open
 Type:               Bug
 Package:            Streams related
 Operating System:   Linux
 PHP Version:        Irrelevant
 Block user comment: N
 Private report:     N

 New Comment:

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.


Previous Comments:
------------------------------------------------------------------------
[2015-03-04 01:05:00] 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-02 20:22:46] 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-02 19:16:32] 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)
...



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=69163&edit=1


Thread (5 messages)

« previous php.bugs (#191184) next »