Bug #75210 [Com]: GlobIterator on current directory uses invalid path for SplFileInfo

From: Date: Thu, 12 Oct 2017 13:36:16 +0000
Subject: Bug #75210 [Com]: GlobIterator on current directory uses invalid path for SplFileInfo
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-211643@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75210&edit=1 ID: 75210 Comment by: thiago dot oak at gmail dot com Reported by: php at pointpro dot nl Summary: GlobIterator on current directory uses invalid path for SplFileInfo Status: Analyzed Type: Bug Package: SPL related Operating System: Ubuntu 16.04 PHP Version: 7.1.9 Block user comment: N Private report: N New Comment: I was looking into this a bit If I understand this correctly it seems that on intern->type = SPL_FS_DIR; // https://github.com/php/php-src/blob/PHP-7.1.9/ext/spl/spl_directory.c#L234 we assume we the "top level" things we iterate are always directories. this works well on places like FilesystemIterator::__construct since they will give you an error if the "top level" is not a dir - "failed to open dir: Not a directory in..." One way I was thinking we could avoid this, is maybe after spprintf(&path, 0, "glob://%s", path); // https://github.com/php/php-src/blob/PHP-7.1.9/ext/spl/spl_directory.c#L719 checking if the 8th char is a * and replacing it with ./* but this feels wrong. not sure what a good solution would be here and Previous Comments: ------------------------------------------------------------------------ [2017-09-15 12:10:24] requinix@php.net It's not that the slash is added but that an implicit "." parent path is not added: the full path constructed is path-from-pattern + "/" + filename, and if the pattern does not have a path then that part is an empty string. https://github.com/php/php-src/blob/PHP-7.1.9/ext/spl/spl_directory.c#L187 Places that use a file name, like getFilename(), recognize that the path is empty and simply return the full path as-is (including the stray leading slash) rather than extract the file name from the full path. What should be happening is that the full path is path-from-pattern + "/" + filename when there is a path, and just filename when there is not. That mirrors how regular SplFileInfo objects work too. This bug technically would affect all the SPL filesystem iterators, however I think GlobIterator is the only one that can be created in a way that uses an empty path name - eg, DirectoryIterator("") says "Directory name must not be empty". Coincidentally, the example for GlobIterator::__construct uses an empty path too but it's written in a way that doesn't reveal the problem :D ------------------------------------------------------------------------ [2017-09-15 11:43:54] sjon at hortensius dot net Can confirm, see https://3v4l.org/aUqLF ------------------------------------------------------------------------ [2017-09-15 10:48:48] php at pointpro dot nl Description: ------------ When using the GlobIterator for the current directory, results depend on the notation. When using, for example, *.php, the resulting SplFileInfo objects will be invalid, while if you use './*.php' they will be valid. Observe the difference in output with the test script. I ran it in a directory containing the script itself as test.php and two other files called test2.php and test3.php It seems that that the GlobIterator adds a '/' at the beginning of the path when I specify no path information, which makes SplFileInfo resolve it as a file in the file system root, which is not correct. I'm tried this using 7.1.9-1+ubuntu16.04.1+deb.sury.org+1 from http://ppa.launchpad.net/ondrej/php/ubuntu and the same also occurs in 7.0.23-1+ubuntu16.04.1+deb.sury.org+1 from that same repository. Test script: --------------- $it = new GlobIterator("./*.php"); foreach ($it as $p) { echo $p->getFilename() . " " . ($p->isFile() ? "IS" : "IS NOT") . " a file\n"; } $it = new GlobIterator("*.php"); foreach ($it as $p) { echo $p->getFilename() . " " . ($p->isFile() ? "IS" : "IS NOT") . " a file\n"; } Expected result: ---------------- ./test.php IS a file ./test2.php IS a file ./test3.php IS a file test.php IS a file test2.php IS a file test3.php IS a file Actual result: -------------- test.php IS a file test2.php IS a file test3.php IS a file /test.php IS NOT a file /test2.php IS NOT a file /test3.php IS NOT a file ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=75210&edit=1

« previous php.bugs (#211643) next »