Skip to content

[16.0][FIX] fs_storage: check rooted_dir paths by whole components, without os.getcwd() - #688

Open
gustavovalverde wants to merge 2 commits into
OCA:16.0from
gustavovalverde:16.0-fix-fs_storage-rooted_dir-join
Open

gustavovalverde wants to merge 2 commits into
OCA:16.0from
gustavovalverde:16.0-fix-fs_storage-rooted_dir-join

Conversation

@gustavovalverde

Copy link
Copy Markdown
Member

Summary

RootedDirFileSystem._join compared paths as text, so it accepted a sibling of its root, such as ../here-backup for the root subdirectory/here. It also called os.getcwd() through make_path_posix, which fails once the working directory is removed (#513). Paths are now normalized as strings and compared by whole components:

- accept if the normalized path starts with the root
+ accept if the normalized path equals the root or starts with the root and a separator

Finishes #522 by @hnavarro-kernet, keeping their commit, as lmignon proposed. Fixes #513.

Review points:

Evidence

The new assertions on 16.0 and with this PR, both on fsspec 2026.9.0. FileNotFoundError means the path got past the check and reached the disk.

                                   before               after
root "subdirectory/here"
  ls("../here-backup")             FileNotFoundError    PermissionError
  ls("..\here-backup")             FileNotFoundError    PermissionError
  cat([file])                      TypeError            {file: data}
root "C:\root" on a "\" filesystem
  _join("..\root-backup")          accepted             PermissionError

All 14 fs_storage tests pass.

Merge Danger

Door: two-way. Nothing is stored or migrated.

Blast Radius: narrow.

Two kinds of paths that used to pass are now refused on every host: paths that climb with backslashes, and any sub path of a root that normalizes to ., such as / on S3, which fsspec reduces to an empty root. 17.0, 18.0, 19.0, and the 20.0 migration #670 have the same check and need forward ports.

Assisted-by: Claude Opus 5.5
Assisted-by: Claude Sonnet 5.5
Assisted-by: Claude Haiku 5.5

hnavarro-kernet and others added 2 commits October 23, 2026 09:41
Before this fix, a FileNotFoundError would ocassionally arise when
'os.getcwd()' is called due to the rooted_dir _join method to check
whether the sub path is part of the parent path.
This is probably caused by the number and/or combination of workers
and threads and the transactions to the FS storage, having race
issues.

After this commit, the sub path is checked if it is contained
inside the parent path virtually via posixpath and pathlib modules
avoiding 'os.getcwd()' calls and running into this possible race
condition.
With the root "subdirectory/here", the path "../here-backup" was
accepted: it normalizes to "subdirectory/here-backup", which starts with
the root as a string. A path is now accepted only when it equals the
root or starts with the root followed by the separator. A root such as
"/" or "C:\" already ends with the separator and keeps its sub paths.

Paths are normalized as strings. On a filesystem whose separator is
"/", a path must stay inside the root under both POSIX and Windows
rules, since fsspec turns a backslash into a slash in local paths on
Windows. A filesystem whose separator is "\" uses the Windows rules, and
any other separator raises ValueError. A list or a dict of paths, which
raised TypeError, is returned as joined, since DirFileSystem checks each
of its paths through this method.

Assisted-by: Claude Opus 5.5
Assisted-by: Claude Haiku 5.5
@oca-cla-bot

oca-cla-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@lmignon

lmignon commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Is-it possible to work without IA. I'm tired to review IA....

@gustavovalverde

gustavovalverde commented Oct 23, 2026 •

Copy link
Copy Markdown
Member Author

Is-it possible to work without IA

I could, but it also helps that I can make contributions that have been thoroughly tested across different deployments, which would take me several hours (maybe a whole working day), instead of 30-45 minutes with the help of AI.

I can make the PR's description shorter if that helps for this and further contributions though (a PR template could also help with that)

Comment on lines +33 to +35
# A backslash is part of a name on most filesystems, but fsspec
# turns it into a slash in local paths on Windows: the path must
# stay inside the root under both rules.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with IA is useless and obscure comment. By debugging the code I understand how it works but do you? This code deserve better explanation...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And please don't ask to your IA. You must be able to explain how it works.

@lmignon

lmignon commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

@gustavovalverde I proposed some changes in gustavovalverde#1 to make the code easier to understand and maintain.

In my opinion, the approach made by the IA using both the POSIX and NT normalizers to normalize POSIX paths is a workaround for a limitation of the POSIX normalizer, which doesn't properly handle paths containing ..\.

I've replaced this workaround with a dedicated method to handle this special case. I think this makes the code easier to read and understand.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants