mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
fix: eliminate TOCTOU races in ln and tac by deferring is_dir() checks (#10991)
* fix: improve error handling for file operations in tac and ln commands * fix: eliminate TOCTOU races in ln and tac by deferring is_dir() checks ln: call hard_link() first, check is_dir() only on failure for diagnostics tac: remove is_dir()/metadata() pre-checks, open file directly and let OS report errors (EISDIR, ENOENT) Closes #9450 * fix(tac): update tests for cross-platform error messages and strip_errno - Remove `(os error 28)` from test_failed_write_is_reported expectation to match the intentional strip_errno() behavior * fix(tac): improve error message formatting for file not found scenario
This commit is contained in:
+17
-12
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore axxbxx bxxaxx axxx axxxx xxaxx xxax xxxxa axyz zyax zyxa bbaaa aaabc bcdddd cddddaaabc xyzabc abcxyzabc nbbaaa
|
||||
// spell-checker:ignore axxbxx bxxaxx axxx axxxx xxaxx xxax xxxxa axyz zyax zyxa bbaaa aaabc bcdddd cddddaaabc xyzabc abcxyzabc nbbaaa EISDIR
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::at_and_ucmd;
|
||||
use uutests::new_ucmd;
|
||||
@@ -83,18 +83,23 @@ fn test_invalid_input() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("b")
|
||||
.fails()
|
||||
.stderr_contains("failed to open 'b' for reading: No such file or directory");
|
||||
#[cfg(not(windows))]
|
||||
let not_found_err = "failed to open 'b' for reading: No such file or directory";
|
||||
#[cfg(windows)]
|
||||
let not_found_err =
|
||||
"failed to open 'b' for reading: The system cannot find the file specified.";
|
||||
|
||||
scene.ucmd().arg("b").fails().stderr_contains(not_found_err);
|
||||
|
||||
at.mkdir("a");
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("a")
|
||||
.fails()
|
||||
.stderr_contains("a: read error: Is a directory");
|
||||
// On Unix, File::open succeeds on directories but read_to_end fails with EISDIR.
|
||||
// On Windows, File::open on a directory fails with "Access is denied".
|
||||
#[cfg(not(windows))]
|
||||
let dir_err = "a: read error: Is a directory";
|
||||
#[cfg(windows)]
|
||||
let dir_err = "failed to open 'a' for reading: Access is denied";
|
||||
|
||||
scene.ucmd().arg("a").fails().stderr_contains(dir_err);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -387,7 +392,7 @@ fn test_failed_write_is_reported() {
|
||||
.pipe_in("hello")
|
||||
.set_stdout(std::fs::File::create("/dev/full").unwrap())
|
||||
.fails()
|
||||
.stderr_is("tac: failed to write to stdout: No space left on device (os error 28)\n");
|
||||
.stderr_is("tac: failed to write to stdout: No space left on device\n");
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
Reference in New Issue
Block a user