[php-src] Issue #15588: directory functions doesn't support IO_REPARSE_TAG_LX_SYMLINK reparse points (Unix/WSL symlinks)
| From: | llde | Date: | Sun, 25 Aug 2024 14:43:28 +0000 |
| Subject: | [php-src] Issue #15588: directory functions doesn't support IO_REPARSE_TAG_LX_SYMLINK reparse points (Unix/WSL symlinks) | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-247592@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/15588
Author: llde
### Description
builtin (extension "standard") function is_file and is_dir doesn't work properly if
the path I'm trying to use these files on contains a unix symlink (IO_REPARSE_TAG_LX_SYMLINK
reparse points).
These functions, before trying to detect if the path point to a file or directory try to get the
real path of the path using the function
tsrm_realpath_r inside zend_vritual_cwd.c where t traverse all path component backwards, opening all
encountered paths.
If one of these paths get a FILE_ATTRIBUTE_REPARSE_POINT attribute, the function try to resolve the
reparse point using FSCTL_GET_REPARSE_POINT DeviceIOControl. It breaks here as the returned type
IO_REPARSE_TAG_LX_SYMLINK isn't handled, exiting the function.
This is a serious issue with "wine" as all native symlinks are treated as
IO_REPARSE_TAG_LX_SYMLINK, and I confirmed that treating the resulting symlink as
IO_REPARSE_TAG_SYMLINK is correcting the issue. It's however a risky change on wine side, as
both symlinks can have a different implementation on filesystem, and I'm not sure if is always
transparent to the application.
tsrm_realpath_r should support IO_REPARSE_TAG_LX_SYMLINK (support should be more trivial then
IO_REPARSE_TAG_SYMLINK, but I'm also finding strange that these functions do traverse the path
in this way. It doesn't seem to add some value at first glance, at least for paths that
contains symlinks, but don't end in symlinks themselves.
I'm bound to using wine here, as I'm using an application Windows only, and it use php for
various operations. But the way the application is starting php don't allow me to replace the
windows version with a native linux version.
Resulted in this output (call done inside the interactive shell):
```
php > $path = "C:\\users\\lorenzo\\Scrivania\\Fanbox";
php > $ret = is_dir($path);
php > var_dump($ret);
bool(false)
```
Scrivania is a symlink to Z:\\home\\lorenzo\\Desktop
But I expected this output instead:
```
php > $path = "C:\\users\\lorenzo\\Scrivania\\Fanbox";
php > $ret = is_dir($path);
php > var_dump($ret);
bool(true)
```
### PHP Version
PHP 8.2.7
### Operating System
ArchLinux (WINE Staging 9.15)