gchp / iota

A terminal-based text editor written in Rust
MIT License
1.64k stars 81 forks source link

(Vi mode) Crash on relative cursor move #129

Closed siiky closed 7 years ago

siiky commented 7 years ago

After doing a few relative line movements (something like 23j23j23j23j23k) it panics.

Backstrace:

     Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/iota --vi README.md`
thread 'main' panicked at 'attempt to subtract with overflow', src/iota/buffer.rs:359
stack backtrace:
   1:     0x7fb312656199 - std::sys::imp::backtrace::tracing::imp::write::hbb14611794d3841b
                        at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:     0x7fb312659dde - std::panicking::default_hook::{{closure}}::h6ed906c7818ac88c
                        at /checkout/src/libstd/panicking.rs:351
   3:     0x7fb3126599e4 - std::panicking::default_hook::h23eeafbf7c1c05c3
                        at /checkout/src/libstd/panicking.rs:367
   4:     0x7fb31265a1db - std::panicking::rust_panic_with_hook::hd0067971b6d1240e
                        at /checkout/src/libstd/panicking.rs:545
   5:     0x7fb31265a064 - std::panicking::begin_panic::h1fd1f10a3de8f902
                        at /checkout/src/libstd/panicking.rs:507
   6:     0x7fb312659fd9 - std::panicking::begin_panic_fmt::haa043917b5d6f21b
                        at /checkout/src/libstd/panicking.rs:491
   7:     0x7fb312659f67 - rust_begin_unwind
                        at /checkout/src/libstd/panicking.rs:467
   8:     0x7fb31267ffad - core::panicking::panic_fmt::he9c7f335d160b59d
                        at /checkout/src/libcore/panicking.rs:69
   9:     0x7fb31267fee4 - core::panicking::panic::hb790668694ff6b20
                        at /checkout/src/libcore/panicking.rs:49
  10:     0x7fb312446525 - iota::buffer::Buffer::get_line_index_backward::h7af8e2be607687fb
                        at /home/silky/projects/iota/src/iota/buffer.rs:359
  11:     0x7fb3124456dd - iota::buffer::Buffer::get_line_index::h7430e5feb14af9e6
                        at /home/silky/projects/iota/src/iota/buffer.rs:277
  12:     0x7fb31244507c - iota::buffer::Buffer::get_object_index::hb567857138d98994
                        at /home/silky/projects/iota/src/iota/buffer.rs:193
  13:     0x7fb312447f21 - iota::buffer::Buffer::set_mark_to_object::h3ddd533843fbf408
                        at /home/silky/projects/iota/src/iota/buffer.rs:562
  14:     0x7fb31244d95c - iota::view::View::move_mark::h11b10e705e8e784c
                        at /home/silky/projects/iota/src/iota/view.rs:364
  15:     0x7fb3124049d8 - <iota::editor::Editor<'e, T>>::handle_instruction::hd21afecf2a78af65
                        at /home/silky/projects/iota/src/iota/editor.rs:253
  16:     0x7fb312403ebe - <iota::editor::Editor<'e, T>>::handle_command::h8ef3d26011a5ad67
                        at /home/silky/projects/iota/src/iota/editor.rs:233
  17:     0x7fb312405d72 - <iota::editor::Editor<'e, T>>::start::hd5f6de36278f485e
                        at /home/silky/projects/iota/src/iota/editor.rs:314
  18:     0x7fb3124100df - iota::main::ha7f9e8a4cc21a0fa
                        at /home/silky/projects/iota/src/main.rs:78
  19:     0x7fb3126610da - __rust_maybe_catch_panic
                        at /checkout/src/libpanic_unwind/lib.rs:98
  20:     0x7fb31265a986 - std::rt::lang_start::hb7fc7ec87b663023
                        at /checkout/src/libstd/panicking.rs:429
                        at /checkout/src/libstd/panic.rs:361
                        at /checkout/src/libstd/rt.rs:57
  21:     0x7fb312410ab2 - main
  22:     0x7fb311e342b0 - __libc_start_main
  23:     0x7fb3123ec369 - _start
  24:                0x0 - <unknown>

The problem seems to be when going to the bottom of the file with relative moves (going one line at a time with j doesn't crash) and then trying to go up. I'm not familiar with the codebase and not too familiar with Rust either but after taking a quick look I found a quick fix.

diff --git a/src/iota/buffer.rs b/src/iota/buffer.rs
index 02c3a1c..11c673d 100644
--- a/src/iota/buffer.rs
+++ b/src/iota/buffer.rs
@@ -356,7 +356,7 @@ impl Buffer {
                         return Some(new_mark_pos)
                     } else {
                         new_mark_pos.absolute = cmp::min(mark_pos.absolute - mark_pos.absolute_line_start + nlines[offset] + 1, nlines[offset-1]);
-                        new_mark_pos.line_number = mark_pos.line_number - offset;
+                        new_mark_pos.line_number = mark_pos.line_number - cmp::min(mark_pos.line_number, offset);
                         new_mark_pos.absolute_line_start = nlines[nlines.len() - 1] + 1;
                     }

It's not pretty but works.

EDIT: Improved patch.

EDIT: Closing, should have made a PR in the first place.