From 9563515e2ebf939a63f92b91e0105ea660e4ec66 Mon Sep 17 00:00:00 2001 From: mattsu Date: Mon, 3 Nov 2025 10:14:58 +0900 Subject: [PATCH] fix(cat): refine unsafe overwrite detection for appending files Refactor the `is_unsafe_overwrite` function to improve logic when appending to files. Previously, the check for zero-sized files was combined with input/output equality, leading to potential false negatives. Now, separate the checks: return false if inputs differ, or if output file is empty. For appending mode, allow safe overwrites if input position is at or beyond file size. This prevents data loss while permitting valid append operations. --- src/uu/cat/src/platform/unix.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/uu/cat/src/platform/unix.rs b/src/uu/cat/src/platform/unix.rs index 8c55c9a4209..b2cdda2aa67 100644 --- a/src/uu/cat/src/platform/unix.rs +++ b/src/uu/cat/src/platform/unix.rs @@ -24,18 +24,29 @@ pub fn is_unsafe_overwrite(input: &I, output: &O) -> bool { let Ok(output_info) = FileInformation::from_file(output) else { return false; }; - if input_info != output_info || output_info.file_size() == 0 { + if input_info != output_info { return false; } - if is_appending(output) { - return true; + let file_size = output_info.file_size(); + if file_size == 0 { + return false; } // `lseek` returns an error if the file descriptor is closed or it refers to // a non-seekable resource (e.g., pipe, socket, or some devices). - let Ok(input_pos) = lseek(input.as_fd(), 0, Whence::SeekCur) else { + let input_pos = lseek(input.as_fd(), 0, Whence::SeekCur); + let output_pos = lseek(output.as_fd(), 0, Whence::SeekCur); + if is_appending(output) { + if let Ok(pos) = input_pos { + if pos >= 0 && (pos as u64) >= file_size { + return false; + } + } + return true; + } + let Ok(input_pos) = input_pos else { return false; }; - let Ok(output_pos) = lseek(output.as_fd(), 0, Whence::SeekCur) else { + let Ok(output_pos) = output_pos else { return false; }; input_pos < output_pos