bypass-finals icon indicating copy to clipboard operation
bypass-finals copied to clipboard

Using is_file() with PHP 8.0

Open PierwszyTV opened this issue 2 years ago • 3 comments

Hi, Is it possible that this package isn't ready for PHP 8.0 yet? I have problem using is_file() function. It executes url_stat(), which uses @$this->native(...), and when the file doesn't exist it throw some exception that is impossible to catch by try-catch block: "stat(): stat failed for 'filename'"

PierwszyTV avatar Apr 14 '22 09:04 PierwszyTV

I've checked it again, and instead of @$this->native(), just put it into try-catch block and it will enough solution.

Screenshot 2022-04-14 at 11 24 01

PierwszyTV avatar Apr 14 '22 09:04 PierwszyTV

@dg Is it possible to fix it soon? Your package is really useful, but without these changes I cannot use it anymore. :(

PierwszyTV avatar Apr 14 '22 09:04 PierwszyTV

That's strange that it doesn't work, because there is a test for that and it passes even in PHP 8.0

https://github.com/dg/bypass-finals/blob/7377e1f8143a75063049c589bd6fb24eeaf430d6/tests/BypassFinals/native.errors.phpt#L78

dg avatar Apr 14 '22 12:04 dg

public function url_stat(string $path, int $flags)
	{
		$func = $flags & STREAM_URL_STAT_LINK ? 'lstat' : 'stat';
		return $flags & STREAM_URL_STAT_QUIET
			? @$this->native($func, $path)
			: $this->native($func, $path);
	}

@PierwszyTV, current implementation url_stat uses error control operator "@" and gets PHP_STREAM_URL_STAT_QUIET flag for is_file function (see https://github.com/php/php-src/blob/master/ext/standard/filestat.c#L793)

So exception can't be thrown Please provide more info for debug

dmitryuk avatar Sep 02 '22 06:09 dmitryuk

Finally I found a way how to reproduce a bug. Try the following code:

(new SplFileInfo('filename'))->isFile()

Result: RuntimeException: stat(): stat failed for filename SplFileInfo::isFile can't throw an exception by guide (link)

@dg any thought how to resolve bug?

dmitryuk avatar Sep 02 '22 09:09 dmitryuk

Please check https://github.com/dg/bypass-finals/pull/34/files

dmitryuk avatar Sep 05 '22 02:09 dmitryuk

@dg This is indeed strange. With one liners on Windows with PHP 8.1.0

$ php -n -r 'require __DIR__ . "/vendor/autoload.php"; DG\BypassFinals::enable(); stat("filename");'

Warning: stat(): stat failed for filename in D:\Web\dev\bypass-finals\src\BypassFinals.php on line 247
Warning: stat(): stat failed for filename in Command line code on line 1

but

$ php -n -r 'require __DIR__ . "/vendor/autoload.php"; DG\BypassFinals::enable(); (new SplFileInfo("filename"))->isFile();'

Fatal error: Uncaught RuntimeException: stat(): stat failed for filename in D:\Web\dev\bypass-finals\src\BypassFinals.php:247
Stack trace:
#0 D:\Web\dev\bypass-finals\src\BypassFinals.php(247): stat('filename')
#1 D:\Web\dev\bypass-finals\src\BypassFinals.php(238): DG\BypassFinals->native('stat', 'filename')
#2 [internal function]: DG\BypassFinals->url_stat('filename', 6)
#3 Command line code(1): SplFileInfo->isFile()
#4 {main}
  thrown in D:\Web\dev\bypass-finals\src\BypassFinals.php on line 247

Looks like an SPL throws an exception. Similar case described here: https://stackoverflow.com/questions/25296178/why-would-phps-stat-throw-a-runtimeexception

Didn't find any PHP bug.

milo avatar Sep 05 '22 11:09 milo

@milo It normally changes the error handler 🤦‍♂️ (in spl_directory.c)

	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
	php_stat(intern->file_name, func_num, return_value); \
	zend_restore_error_handling(&error_handling); \

dg avatar Sep 06 '22 03:09 dg