hhvm icon indicating copy to clipboard operation
hhvm copied to clipboard

Opening empty directory with RecursiveDirectoryIterator

Open ggottwald opened this issue 9 years ago • 11 comments

HHVM Version

3.12.7 - PHP 5.6.20 is ok

Standalone code, or other way to reproduce the problem

https://gist.github.com/ggottwald/93c0b5412fd0371220f644c93c9aaa30

Expected result

realPath: false, dir: true

Actual result

realPath: current script directory, dir: false

ggottwald avatar Aug 18 '16 09:08 ggottwald

Can you be clearer about the reproduction code? It looks like it's just creating a new RecursiveDirectoryIterator() on the same blank directory twice. When I try that it works fine.

aorenste avatar Sep 29 '16 18:09 aorenste

For this output I used artisan tinker. But the results is the same in productive php code. I created an empty directory "/tmp/bla". By creating an instance of RecursiveDirecotryIterator (new \RecursiveDirectoryIterator('/tmp/bla', 4096);) its getting an empty path and dir:false.

Just testet in hhvm 3.15.0.

ggottwald avatar Sep 29 '16 19:09 ggottwald

@aorenste I ran some tests with this with the following result:

php5.6 test.php 
string(3) "bla"
php7.0 test.php 
string(3) "bla"
hhvm test.php
string(0) ""
hhvm -d hhvm.php7.all=1 test.php          

Fatal error: Uncaught TypeError: Argument 1 passed to dirname() must be an instance of string, bool given in /home/wolverine/tests/hhvm_recursive_directory_operator/test.php:6
Stack trace:
#0 (): dirname()
#1 /home/wolverine/tests/hhvm_recursive_directory_operator/test.php(6): SplFileInfo->getPath()
#2 {main}

Testcode

<?php
@rmdir('bla');
mkdir('bla');
$iterator = new \RecursiveDirectoryIterator('bla', 4096);

var_dump($iterator->getPath());

usox avatar Jun 05 '17 12:06 usox

I stumbled across this when trying to use composer in php7 mode. symfony/finder@d04fb01c1aa6e3f2f62e5505b62ede74f7cd4d1a is related to this problem as its the piece of code which breaks composer by calling getPath. Adding a validity-check before calling getPath solves the problem for me, but not the problem itself.

usox avatar Jun 05 '17 12:06 usox

Ok, some more details after digging a bit. Hhvms DirectoryIterator::next() passes a boolean false to the underlying SplFileInfo::setPathName. SplFileInfo::getPath() invokes dirname with this bool which leads to an error in php7-mode with enabled scalar types. When using hhvm.php7.scalar_types=0, getPath returns just an empty string, php however returns the initial directory path. My solution would be to implement a getPath method in the DirectoryIterator which returns the initial path. The result of SplFileInfo::getPath is not useable due to the usage of dirname.

usox avatar Jun 05 '17 19:06 usox

Related #7869

usox avatar Jun 06 '17 21:06 usox

<?php

class Foo {
  public function __toString() {
      return 'stringable';
  }
}

$inputs = [null, false, true, 0, 1, new Foo()];

foreach ($inputs as $input) {
  $sfi = new SplFileInfo($input);
  print("-----\n");
  var_export($input);
  print("\n");
  var_export($sfi->getPathname());
  print("\n");
  var_export($sfi->getPath());
  print("\n");
}

https://3v4l.org/JcZaf

fredemmott avatar Jun 06 '17 21:06 fredemmott

:( got the actual fix ready, but might take a while to land because this also needs to be fixed:

https://3v4l.org/KE4BX

fredemmott avatar Jun 06 '17 22:06 fredemmott

Also https://3v4l.org/rUXUl

fredemmott avatar Jun 06 '17 22:06 fredemmott

Yep, directly fixing this breaks DirectoryIterator.

fredemmott avatar Jun 07 '17 15:06 fredemmott

Made a smaller (safer) fix just for the dirname() throw in SplFileInfo; fixes composer, but not the broader issue here. Will revisit this soon hopefully.

fredemmott avatar Jun 07 '17 16:06 fredemmott