Skip to content

Commit 4fedd50

Browse files
authored
fix: file edit operation by adding bounds check (#20)
* fix:handle invalid file edit requests gracefully * chore: improve slice logic to handle edge cases
1 parent 68da679 commit 4fedd50

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/fs_service.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,21 @@ impl FileSystemService {
512512

513513
let mut match_found = false;
514514

515-
for i in 0..=content_lines.len() - old_lines.len() {
515+
// skip when the match is impossible:
516+
if old_lines.len() > content_lines.len() {
517+
let error_message = format!(
518+
"Cannot apply edit: the original text spans more lines ({}) than the file content ({}).",
519+
old_lines.len(),
520+
content_lines.len()
521+
);
522+
523+
return Err(RpcError::internal_error()
524+
.with_message(error_message)
525+
.into());
526+
}
527+
528+
let max_start = content_lines.len().saturating_sub(old_lines.len());
529+
for i in 0..=max_start {
516530
let potential_match = &content_lines[i..i + old_lines.len()];
517531

518532
// Compare lines with normalized whitespace

tests/test_fs_service.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,3 +896,30 @@ async fn test_preserve_unix_line_endings() {
896896
let updated = std::fs::read_to_string(&file).unwrap();
897897
assert_eq!(updated, "updated1\nupdated2\n"); // Still uses \n endings
898898
}
899+
900+
#[tokio::test]
901+
// Issue #19: https://github.com/rust-mcp-stack/rust-mcp-filesystem/issues/19
902+
async fn test_panic_on_out_of_bounds_edit() {
903+
let (temp_dir, service) = setup_service(vec!["dir1".to_string()]);
904+
905+
// Set up an edit that expects to match 5 lines
906+
let edit = EditOperation {
907+
old_text: "line e\n".repeat(41).to_string(),
908+
new_text: "replaced content".to_string(),
909+
};
910+
911+
// Set up your file content with only 2 lines
912+
let file_content = "line A\nline B\n";
913+
let test_path = create_temp_file(
914+
&temp_dir.as_path().join("dir1"),
915+
"test_input.txt",
916+
file_content,
917+
);
918+
919+
let result = service
920+
.apply_file_edits(&test_path, vec![edit], Some(true), None)
921+
.await;
922+
923+
// It should panic without the fix, or return an error after applying the fix
924+
assert!(result.is_err());
925+
}

0 commit comments

Comments
 (0)