Repository navigation
fix(realpath): reject non-directory path components and forcing them to ENOTDIR #16153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1dcc362
432d1d7
3f9d8a0
c1998f7
1e809ed
42387c3
ebdec2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,11 @@ use std::path::{MAIN_SEPARATOR, Path}; | |
|
|
||
| static GIBBERISH: &str = "supercalifragilisticexpialidocious"; | ||
|
|
||
| #[cfg(not(windows))] | ||
| static NOT_A_DIRECTORY: &str = "Not a directory"; | ||
| #[cfg(windows)] | ||
| static NOT_A_DIRECTORY: &str = "The directory name is invalid."; | ||
|
|
||
| #[test] | ||
| #[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] | ||
| fn test_realpath_current_directory() { | ||
|
|
@@ -670,3 +675,153 @@ fn test_realpath_canonicalize_vs_existing() { | |
| } | ||
| } | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_realpath_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.touch("regular_file"); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("regular_file/..") | ||
| .fails() | ||
| .code_is(1) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the issue also mentions -L, -e and readlink -f, please add tests for them
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes i totaly forgot to add Logical path support . |
||
| .stderr_contains(NOT_A_DIRECTORY) | ||
| .no_stdout(); | ||
| } | ||
|
|
||
| #[test] | ||
| #[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] | ||
| fn test_realpath_directory_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.mkdir("directory"); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("directory/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the other tests using root_dir_resolved() have
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| } | ||
|
|
||
| #[test] | ||
| #[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] | ||
| fn test_realpath_directory_followed_by_parent_dir_missing_mode() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please also test |
||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("-m") | ||
| .arg("missing/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
| } | ||
|
|
||
| #[test] | ||
| #[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] | ||
| fn test_realpath_strip_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.mkdir("directory"); | ||
| at.touch("regular_file"); | ||
|
|
||
| // With `-s` (no symlink resolution), GNU still validates that the | ||
| // component preceding `..` is an existing directory. | ||
| scene | ||
| .ucmd() | ||
| .arg("-s") | ||
| .arg("directory/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("-s") | ||
| .arg("regular_file/..") | ||
| .fails() | ||
| .code_is(1) | ||
| .stderr_contains(NOT_A_DIRECTORY) | ||
| .no_stdout(); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("-s") | ||
| .arg("missing/..") | ||
| .fails() | ||
| .code_is(1) | ||
| .stderr_contains("No such file or directory") | ||
| .no_stdout(); | ||
|
|
||
| // `-m` relaxes the directory/existence check, so these succeed even | ||
| // combined with `-s`. | ||
| scene | ||
| .ucmd() | ||
| .args(&["-s", "-m"]) | ||
| .arg("regular_file/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .args(&["-s", "-m"]) | ||
| .arg("missing/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
| } | ||
|
|
||
| #[test] | ||
| #[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] | ||
| fn test_realpath_missing_mode_regular_file_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.touch("regular_file"); | ||
|
|
||
| // `-m` permits missing and non-directory components, so a regular file | ||
| // followed by `..` must succeed (matching GNU). | ||
| scene | ||
| .ucmd() | ||
| .arg("-m") | ||
| .arg("regular_file/..") | ||
| .succeeds() | ||
| .stdout_is(format!("{}\n", at.root_dir_resolved())); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_realpath_logical_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.touch("regular_file"); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("-L") | ||
| .arg("regular_file/..") | ||
| .fails() | ||
| .code_is(1) | ||
| .stderr_contains(NOT_A_DIRECTORY) | ||
| .no_stdout(); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_realpath_existing_followed_by_parent_dir() { | ||
| let scene = TestScenario::new(util_name!()); | ||
| let at = &scene.fixtures; | ||
|
|
||
| at.touch("regular_file"); | ||
|
|
||
| scene | ||
| .ucmd() | ||
| .arg("-e") | ||
| .arg("regular_file/..") | ||
| .fails() | ||
| .code_is(1) | ||
| .stderr_contains(NOT_A_DIRECTORY) | ||
| .no_stdout(); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this also runs with -s (ResolveMode::None), so
realpath -s file/..and-s missing/..change toocould you please check what GNU does and add a -s test?