php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78939 file_exists produces different results with TS and NTS builds
Submitted: 2019-12-10 11:28 UTC Modified: 2020-01-20 08:26 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: michael dot vorisek at email dot cz Assigned:
Status: Open Package: *Directory/Filesystem functions
PHP Version: 7.3.12 OS: Windows
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: michael dot vorisek at email dot cz
New email:
PHP Version: OS:

 

 [2019-12-10 11:28 UTC] michael dot vorisek at email dot cz
Description:
------------
After spending a lot of time why PHP app does work on one PC and not on another, comparing gigabytes of logs, I find very weird behaviour of core PHP file function.

var_dump(file_exists('C:x.txt'));

if the file "C:/x.txt" exists, PHP produces different results with TS and NTS builds on Windows if the path is without slash after "C:", i.e.
- output for "C:/x.txt" is corrent and consitent across TS and NTS builds
- output for "C:x.txt" differs across TS and NTS builds

The path format without slash after "C:" is not supported in explorer.exe, so for me it seems that paths like "C:something" should be considered invalid and the TS build should be fixed to always return false.

Note: other file functions are probably affected too.

Test script:
---------------
// 1. manually create any/empty file and save it under "C:/x.txt"

// 2. run this code with PHP TS and PHP NTS
var_dump(ZEND_THREAD_SAFE);
var_dump(file_exists('C:/x.txt'));
var_dump(file_exists('C:x.txt'));

// 3. notice the different output of the 3rd line

Expected result:
----------------
// expected output from PHP TS and NTS
bool(true) OR bool(false) // dump of ZEND_THREAD_SAFE constant
bool(true)
bool(true) OR bool(false) // TBD, path without slash after "C:" - see desc., but output need to be consistent across TS and NTS PHP builds

Actual result:
--------------
// output from PHP TS
bool(true)
bool(true)
bool(true)

// output from PHP NTS
bool(false)
bool(true)
bool(false)

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-12-10 11:38 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2019-12-10 11:38 UTC] requinix@php.net
C:x.txt is a valid path: it references x.txt in the process's current working directory on the C drive.
https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats

I imagine the NTS build is inheriting the C: working directory from whatever process you used to spawn it. This would be one of those "different in more ways than just threading" aspects I mentioned in the other report.

Ultimately it is a relative path, and relative paths are subject to the environment.
 [2019-12-10 12:58 UTC] michael dot vorisek at email dot cz
Yes, if relative path with drive letter should be supported, PHP must process it the same way it resolves standard relative paths like '../x.txt' and support php.ini directived like include_path.

Or simply remove the support for it and display PHP warning, as the format is very confusing, not supported even by explorer.exe (but other relative formats are) and a lot of people are not aware of it.
 [2019-12-10 13:06 UTC] requinix@php.net
There's no support to remove. It's Windows doing this, not PHP. What you want is to *add a restriction* that PHP on Windows will not allow an uncommon but very much valid pattern for a file path.
And what's the rationale for this, again? Because "a lot of people are not aware of it"? Got anything better?
 [2019-12-10 13:22 UTC] requinix@php.net
That might have been a bit blunt. My point is, you had some sort of problem that you tracked down (congratulations) to some sort of incorrect file path configuration... code... something. And now you have learned that "C:x.txt" and "C:/x.txt" can potentially mean two different things because the former is a relative path and the latter is absolute.

Normally this sort of situation becomes resolved at this point because it's considered an issue of user education, and once the teaching is done and the code is fixed, everything starts working again. But you're apparently looking for something more and I, personally, am not seeing what should happen next. It's not like the behavior is wrong - maybe it's a bit unexpected, but that isn't PHP's fault. The only thing I can think of is documentation, but there are *tons* of little Windows nuances out there and I don't think it's reasonable to expect PHP to try to cover them. Prohibit the unusual behavior? That seems like it would punish more people for using the feature than help people who were accidentally using it (and somehow not noticing a problem?).
 [2019-12-10 13:30 UTC] michael dot vorisek at email dot cz
Yes, only contemplation for easier fix and to prevent missuses...

The current issue is that PHP does not resolves relative paths the same way.

The expected behaviour is, if your current directory is in C: drive, then all usages like: "x.txt", "./x.txt" and "C:x.txt" point to the same file.
 [2019-12-10 14:12 UTC] requinix@php.net
And if your expected behavior on Windows is that "C:/x.txt" and "C:/X.TXT" are two different files, you would be equally wrong.
 [2019-12-10 14:28 UTC] michael dot vorisek at email dot cz
No! I am just reporting, that relative path with drive letter is not resolved correctly.

If this path format should be supported, it needs to be resolved like PHP resolve any other relative relative paths. PHP currently ignores this fact completely and resolves relative paths with drive letter like absolute ones.
 [2019-12-10 14:52 UTC] fgfgfgfdf at somewhere dot com
> PHP currently ignores this fact completely and resolves 
> relative paths with drive letter like absolute ones

PHP resolves nothing, windows does
 [2019-12-10 18:13 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #78939 - Windows relative path with drive letter
On GitHub:  https://github.com/php/php-src/pull/5001
Patch:      https://github.com/php/php-src/pull/5001.patch
 [2019-12-10 18:14 UTC] cmb@php.net
-Status: Feedback +Status: Open -Assigned To: +Assigned To: cmb
 [2019-12-10 18:14 UTC] cmb@php.net
This may very well be an issue of the PHP implementation.
 [2020-01-20 08:26 UTC] cmb@php.net
-Status: Assigned +Status: Open -Assigned To: cmb +Assigned To:
 [2023-07-05 10:16 UTC] fisska at gmail dot com
1. Path format: In PHP, the file path format may vary depending on the operating system. On Windows, both forward slashes (`/`) and backslashes (`\`) are generally accepted as directory separators. However, when using backslashes, you need to be careful because they are also escape characters in PHP strings. So, when using backslashes, you need to escape them or use double backslashes (`\\`) in the file path.

2. PHP build: The TS (Thread Safe) and NTS (Non-Thread Safe) builds of PHP can sometimes exhibit slight differences in behavior. These differences are mainly related to the underlying threading models used by PHP. It's possible that the way file functions handle paths can vary between the TS and NTS builds.

3. File path validation: PHP does not strictly validate file paths by default. It relies on the underlying operating system to handle file operations. If a file path is not recognized as a valid path by the operating system, PHP's behavior may become unpredictable.

To address the issue you encountered, here are a few suggestions:

- Use the recommended file path format: It's generally recommended to use forward slashes (`/`) or double backslashes (`\\`) when specifying file paths in PHP, regardless of the operating system. This can help ensure consistency and compatibility across different PHP builds.

- Normalize file paths: Before using file paths in PHP functions, it's a good practice to normalize them using the `realpath` function. This function resolves any relative paths and returns the absolute path, which can help avoid inconsistencies caused by different path formats (https://github.com)(https://www.tellhappystar.org/).

- Be cautious with path assumptions: When working with file paths, it's important to consider the assumptions made by different operating systems and PHP builds. Avoid relying on non-standard path formats or behavior that may not be consistent across environments.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Mar 03 04:01:28 2024 UTC