From b079d1c806547b490988e096ebb34886a860e8d2 Mon Sep 17 00:00:00 2001 From: Ali Hashemi Date: Thu, 29 May 2025 18:14:29 -0300 Subject: [PATCH 1/2] fix:handle invalid file edit requests gracefully --- src/fs_service.rs | 13 +++++++++++++ tests/test_fs_service.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/fs_service.rs b/src/fs_service.rs index 7afeea9..7d457ce 100644 --- a/src/fs_service.rs +++ b/src/fs_service.rs @@ -512,6 +512,19 @@ impl FileSystemService { let mut match_found = false; + // skip when the match is impossible: + if old_lines.len() > content_lines.len() { + let error_message = format!( + "Cannot apply edit: the original text spans more lines ({}) than the file content ({}).", + old_lines.len(), + content_lines.len() + ); + + return Err(RpcError::internal_error() + .with_message(error_message) + .into()); + } + for i in 0..=content_lines.len() - old_lines.len() { let potential_match = &content_lines[i..i + old_lines.len()]; diff --git a/tests/test_fs_service.rs b/tests/test_fs_service.rs index bb3b2ea..cd8ae1c 100644 --- a/tests/test_fs_service.rs +++ b/tests/test_fs_service.rs @@ -896,3 +896,30 @@ async fn test_preserve_unix_line_endings() { let updated = std::fs::read_to_string(&file).unwrap(); assert_eq!(updated, "updated1\nupdated2\n"); // Still uses \n endings } + +#[tokio::test] +// Issue #19: https://github.com/rust-mcp-stack/rust-mcp-filesystem/issues/19 +async fn test_panic_on_out_of_bounds_edit() { + let (temp_dir, service) = setup_service(vec!["dir1".to_string()]); + + // Set up an edit that expects to match 5 lines + let edit = EditOperation { + old_text: "line e\n".repeat(41).to_string(), + new_text: "replaced content".to_string(), + }; + + // Set up your file content with only 2 lines + let file_content = "line A\nline B\n"; + let test_path = create_temp_file( + &temp_dir.as_path().join("dir1"), + "test_input.txt", + file_content, + ); + + let result = service + .apply_file_edits(&test_path, vec![edit], Some(true), None) + .await; + + // It should panic without the fix, or return an error after applying the fix + assert!(result.is_err()); +} From 9a19df77746df555a288a93fd0d59e41b9c035a5 Mon Sep 17 00:00:00 2001 From: Ali Hashemi Date: Thu, 29 May 2025 18:17:23 -0300 Subject: [PATCH 2/2] chore: improve slice logic to handle edge cases --- src/fs_service.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fs_service.rs b/src/fs_service.rs index 7d457ce..7677b1f 100644 --- a/src/fs_service.rs +++ b/src/fs_service.rs @@ -525,7 +525,8 @@ impl FileSystemService { .into()); } - for i in 0..=content_lines.len() - old_lines.len() { + let max_start = content_lines.len().saturating_sub(old_lines.len()); + for i in 0..=max_start { let potential_match = &content_lines[i..i + old_lines.len()]; // Compare lines with normalized whitespace