Repository: tursodatabase/limbo (language: rust)

Issue:
non-terminated literal causes infinite loop
this command is able to generate infinite loops

limbo> select concat('
(x1...> ;

× non-terminated literal at (1, 15)
 non-terminated literal at (1, 15)

the same using stdin



Discussion / hints:

Fix patch:
diff --git a/cli/app.rs b/cli/app.rs
index 7941e90e1..4bdeeb788 100644
--- a/cli/app.rs
+++ b/cli/app.rs
@@ -310,13 +310,7 @@ impl Limbo {
         if cmd.trim().starts_with('.') {
             self.handle_dot_command(cmd);
         } else {
-            let conn = self.conn.clone();
-            let runner = conn.query_runner(cmd.as_bytes());
-            for output in runner {
-                if let Err(e) = self.print_query_result(cmd, output) {
-                    let _ = self.writeln(e.to_string());
-                }
-            }
+            self.run_query(cmd);
         }
         std::process::exit(0);
     }
@@ -434,6 +428,21 @@ impl Limbo {
         self.input_buff.push(' ');
     }
 
+    fn run_query(&mut self, input: &str) {
+        let echo = self.opts.echo;
+        if echo {
+            let _ = self.writeln(&input);
+        }
+        let conn = self.conn.clone();
+        let runner = conn.query_runner(input.as_bytes());
+        for output in runner {
+            if let Err(_) = self.print_query_result(&input, output) {
+                break;
+            }
+        }
+        self.reset_input();
+    }
+
     pub fn handle_input_line(
         &mut self,
         line: &str,
@@ -458,17 +467,7 @@ impl Limbo {
                     self.buffer_input(after_comment);
 
                     if after_comment.ends_with(';') {
-                        if self.opts.echo {
-                            let _ = self.writeln(after_comment);
-                        }
-                        let conn = self.conn.clone();
-                        let runner = conn.query_runner(after_comment.as_bytes());
-                        for output in runner {
-                            if let Err(e) = self.print_query_result(after_comment, output) {
-                                let _ = self.writeln(e.to_string());
-                            }
-                        }
-                        self.reset_input();
+                        self.run_query(after_comment);
                     } else {
                         self.set_multiline_prompt();
                     }
@@ -489,18 +488,7 @@ impl Limbo {
         if line.ends_with(';') {
             self.buffer_input(line);
             let buff = self.input_buff.clone();
-            let echo = self.opts.echo;
-            if echo {
-                let _ = self.writeln(&buff);
-            }
-            let conn = self.conn.clone();
-            let runner = conn.query_runner(buff.as_bytes());
-            for output in runner {
-                if let Err(e) = self.print_query_result(&buff, output) {
-                    let _ = self.writeln(e.to_string());
-                }
-            }
-            self.reset_input();
+            self.run_query(buff.as_str());
         } else {
             self.buffer_input(line);
             self.set_multiline_prompt();
@@ -745,6 +733,7 @@ impl Limbo {
                     "{:?}",
                     miette::Error::from(err).with_source_code(sql.to_owned())
                 ));
+                anyhow::bail!("We have to throw here, even if we printed error");
             }
         }
         // for now let's cache flush always
@@ -881,17 +870,7 @@ impl Limbo {
         }
 
         let buff = self.input_buff.clone();
-        let echo = self.opts.echo;
-        if echo {
-            let _ = self.writeln(&buff);
-        }
-        let conn = self.conn.clone();
-        let runner = conn.query_runner(buff.as_bytes());
-        for output in runner {
-            if let Err(e) = self.print_query_result(&buff, output) {
-                let _ = self.writeln(e.to_string());
-            }
-        }
+        self.run_query(buff.as_str());
         self.reset_input();
     }
 }


Test patch: