Visitar URL original
[4.x] Fix Path::clean() and Path::resolve() for short paths and Windows drives by Hackwar · Pull Request #103 · joomla-framework/filesystem · GitHub
Skip to content

[4.x] Fix Path::clean() and Path::resolve() for short paths and Windows drives - #103

Open
Hackwar wants to merge 1 commit into
joomla-framework:4.x-devfrom
Hackwar:4.x-path-clean-offsets
Open

Hackwar wants to merge 1 commit into
joomla-framework:4.x-devfrom
Hackwar:4.x-path-clean-offsets

Conversation

@Hackwar

@Hackwar Hackwar commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

  • Path::clean() checked $path[0] and $path[1] after trim() without a length check, so with $ds = '\\' both clean(' ') and clean('\\') raised Uninitialized string offset warnings. It now uses str_starts_with().
  • Path::resolve('') read $path[0] and raised the same warning. It now returns ''.
  • On Windows resolve() let .. remove the drive: resolve('C:\..\Windows') returned the relative path Windows instead of throwing. A leading drive (C:) is now treated like the root, so climbing above it throws "Path is outside of the defined root" as it does for /.. on Unix. Paths below the drive resolve as before (C:/var/www/foo/../joomla → C:\var\www\joomla). The drive handling is limited to Windows, so the behaviour on other systems is unchanged.

Testing Instructions

  • PathTest::testShortPathsDoNotRaiseWarnings collects warnings from clean(' ', '\\'), clean('\\', '\\') and resolve(''): three warnings before, none after. New getCleanData/getResolveData rows cover the same inputs.
  • PathTest::testResolveKeepsWindowsDrive (Windows only): resolve('C:\a\..\b') is C:\b, resolve('C:\..\Windows') throws. Before, the latter returned Windows.

Documentation Changes Required

docs/overview.md gets a "Cleaning and resolving paths" section.

#88 rewrites docs/overview.md; whichever of the two is merged second has to resolve the conflict there. #88's "Paths" section ("resolve() throws a FilesystemException when the path climbs above its own root") stays correct and could mention the Windows drive.

🤖 Generated with Claude Code

clean() checked $path[0] and $path[1] without checking the length, so
clean(' ') and clean('\\') with a backslash separator raised
"Uninitialized string offset" warnings, as did resolve(''). On Windows
resolve() let ".." remove the drive, so resolve('C:\..\Windows')
returned the relative path 'Windows' instead of throwing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Hackwar

Hackwar commented Nov 12, 2026

Copy link
Copy Markdown
Contributor Author

The CI failures are unrelated to this change and occur on 4.x-dev as well (see its scheduled runs):

  • Unit tests: the only failing test is HelperTest::testRemotefsize. https://www.example.org no longer sends a Content-Length header, so Helper::remotefsize() returns false. [4.x] Fix Stream reads at EOF, of "0" chunks and of Windows paths #88 makes that test skip when the header is missing.
  • Unit tests (Windows) (8.3): composer install --ignore-platform-reqs installs a PHPUnit release that requires PHP 8.4, so PHPUnit refuses to start ("This version of PHPUnit requires PHP >= 8.4.1"). Whichever Windows job fails first cancels the other (fail-fast).
  • PHPStan (non-blocking, continue-on-error): reports the existing errors in FtpClient and File::isSafeFile(). This change adds no new ones.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant