diff options
author | gavynriebau | 2022-06-05 10:49:41 +0000 |
---|---|---|
committer | GitHub | 2022-06-05 10:49:41 +0000 |
commit | b2bd87df81756d4925bf1f4da6962b9dd83a807c (patch) | |
tree | f6b9779481454745a0f0efc97226cd7b9ab38029 | |
parent | 1c2aaf3bafd363ac5efd4befdb1d65bf5895769f (diff) |
Fix crash due to cycles when replaying macros (#2647)
In certain circumstances it was possible to get into an infinite loop
when replaying macros such as when different macros attempt to replay
each other.
This commit adds changes to track which macros are currently being
replayed and prevent getting into infinite loops.
-rw-r--r-- | helix-term/src/commands.rs | 13 | ||||
-rw-r--r-- | helix-view/src/editor.rs | 2 |
2 files changed, 15 insertions, 0 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 44e2f8c2..e7efa6c3 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4617,6 +4617,17 @@ fn record_macro(cx: &mut Context) { fn replay_macro(cx: &mut Context) { let reg = cx.register.unwrap_or('@'); + + if cx.editor.macro_replaying.contains(®) { + cx.editor.set_error(format!( + "Cannot replay from register [{}] because already replaying from same register", + reg + )); + return; + } + + cx.editor.macro_replaying.push(reg); + let keys: Vec<KeyEvent> = if let Some([keys_str]) = cx.editor.registers.read(reg) { match helix_view::input::parse_macro(keys_str) { Ok(keys) => keys, @@ -4638,4 +4649,6 @@ fn replay_macro(cx: &mut Context) { } } })); + + cx.editor.macro_replaying.pop(); } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index f2fb4301..8e53936a 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -433,6 +433,7 @@ pub struct Editor { pub selected_register: Option<char>, pub registers: Registers, pub macro_recording: Option<(char, Vec<KeyEvent>)>, + pub macro_replaying: Vec<char>, pub theme: Theme, pub language_servers: helix_lsp::Registry, @@ -503,6 +504,7 @@ impl Editor { count: None, selected_register: None, macro_recording: None, + macro_replaying: Vec::new(), theme: theme_loader.default(), language_servers, debugger: None, |