Fix a panic in merge conflict parsing (#32119)

Cole Miller created

Release Notes:

- Fixed a panic that could occur when editing files containing merge
conflicts.

Change summary

crates/project/src/git_store/conflict_set.rs | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)

Detailed changes

crates/project/src/git_store/conflict_set.rs 🔗

@@ -171,7 +171,8 @@ impl ConflictSet {
         let mut conflicts = Vec::new();
 
         let mut line_pos = 0;
-        let mut lines = buffer.text_for_range(0..buffer.len()).lines();
+        let buffer_len = buffer.len();
+        let mut lines = buffer.text_for_range(0..buffer_len).lines();
 
         let mut conflict_start: Option<usize> = None;
         let mut ours_start: Option<usize> = None;
@@ -212,7 +213,7 @@ impl ConflictSet {
                 && theirs_start.is_some()
             {
                 let theirs_end = line_pos;
-                let conflict_end = line_end + 1;
+                let conflict_end = (line_end + 1).min(buffer_len);
 
                 let range = buffer.anchor_after(conflict_start.unwrap())
                     ..buffer.anchor_before(conflict_end);
@@ -390,6 +391,22 @@ mod tests {
         assert_eq!(their_text, "This is their version in a nested conflict\n");
     }
 
+    #[test]
+    fn test_conflict_markers_at_eof() {
+        let test_content = r#"
+            <<<<<<< ours
+            =======
+            This is their version
+            >>>>>>> "#
+            .unindent();
+        let buffer_id = BufferId::new(1).unwrap();
+        let buffer = Buffer::new(0, buffer_id, test_content.to_string());
+        let snapshot = buffer.snapshot();
+
+        let conflict_snapshot = ConflictSet::parse(&snapshot);
+        assert_eq!(conflict_snapshot.conflicts.len(), 1);
+    }
+
     #[test]
     fn test_conflicts_in_range() {
         // Create a buffer with conflict markers