]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.3259: when 'indentexpr' causes an error did_throw may hang v8.2.3259
authorBram Moolenaar <Bram@vim.org>
Sat, 31 Jul 2021 19:32:31 +0000 (21:32 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 31 Jul 2021 19:32:31 +0000 (21:32 +0200)
Problem:    When 'indentexpr' causes an error the did_throw flag may remain
            set.
Solution:   Reset did_throw and show the error. (closes #8677)

src/ex_docmd.c
src/indent.c
src/proto/ex_docmd.pro
src/version.c

index fbfba52dd4063401c08aeb36a42d47f667c8607e..61feda257dc25ff87d279b02b1e5c23b5638dffc 100644 (file)
@@ -1268,67 +1268,7 @@ do_cmdline(
         * commands are executed.
         */
        if (did_throw)
-       {
-           char        *p = NULL;
-           msglist_T   *messages = NULL;
-
-           /*
-            * If the uncaught exception is a user exception, report it as an
-            * error.  If it is an error exception, display the saved error
-            * message now.  For an interrupt exception, do nothing; the
-            * interrupt message is given elsewhere.
-            */
-           switch (current_exception->type)
-           {
-               case ET_USER:
-                   vim_snprintf((char *)IObuff, IOSIZE,
-                           _("E605: Exception not caught: %s"),
-                           current_exception->value);
-                   p = (char *)vim_strsave(IObuff);
-                   break;
-               case ET_ERROR:
-                   messages = current_exception->messages;
-                   current_exception->messages = NULL;
-                   break;
-               case ET_INTERRUPT:
-                   break;
-           }
-
-           estack_push(ETYPE_EXCEPT, current_exception->throw_name,
-                                               current_exception->throw_lnum);
-           ESTACK_CHECK_SETUP
-           current_exception->throw_name = NULL;
-
-           discard_current_exception();        // uses IObuff if 'verbose'
-           suppress_errthrow = TRUE;
-           force_abort = TRUE;
-
-           if (messages != NULL)
-           {
-               do
-               {
-                   msglist_T   *next = messages->next;
-                   int         save_compiling = estack_compiling;
-
-                   estack_compiling = messages->msg_compiling;
-                   emsg(messages->msg);
-                   vim_free(messages->msg);
-                   vim_free(messages->sfile);
-                   vim_free(messages);
-                   messages = next;
-                   estack_compiling = save_compiling;
-               }
-               while (messages != NULL);
-           }
-           else if (p != NULL)
-           {
-               emsg(p);
-               vim_free(p);
-           }
-           vim_free(SOURCING_NAME);
-           ESTACK_CHECK_NOW
-           estack_pop();
-       }
+           handle_did_throw();
 
        /*
         * On an interrupt or an aborting error not converted to an exception,
@@ -1448,6 +1388,73 @@ do_cmdline(
     return retval;
 }
 
+/*
+ * Handle when "did_throw" is set after executing commands.
+ */
+    void
+handle_did_throw()
+{
+    char       *p = NULL;
+    msglist_T  *messages = NULL;
+
+    /*
+     * If the uncaught exception is a user exception, report it as an
+     * error.  If it is an error exception, display the saved error
+     * message now.  For an interrupt exception, do nothing; the
+     * interrupt message is given elsewhere.
+     */
+    switch (current_exception->type)
+    {
+       case ET_USER:
+           vim_snprintf((char *)IObuff, IOSIZE,
+                   _("E605: Exception not caught: %s"),
+                   current_exception->value);
+           p = (char *)vim_strsave(IObuff);
+           break;
+       case ET_ERROR:
+           messages = current_exception->messages;
+           current_exception->messages = NULL;
+           break;
+       case ET_INTERRUPT:
+           break;
+    }
+
+    estack_push(ETYPE_EXCEPT, current_exception->throw_name,
+                                       current_exception->throw_lnum);
+    ESTACK_CHECK_SETUP
+    current_exception->throw_name = NULL;
+
+    discard_current_exception();       // uses IObuff if 'verbose'
+    suppress_errthrow = TRUE;
+    force_abort = TRUE;
+
+    if (messages != NULL)
+    {
+       do
+       {
+           msglist_T   *next = messages->next;
+           int         save_compiling = estack_compiling;
+
+           estack_compiling = messages->msg_compiling;
+           emsg(messages->msg);
+           vim_free(messages->msg);
+           vim_free(messages->sfile);
+           vim_free(messages);
+           messages = next;
+           estack_compiling = save_compiling;
+       }
+       while (messages != NULL);
+    }
+    else if (p != NULL)
+    {
+       emsg(p);
+       vim_free(p);
+    }
+    vim_free(SOURCING_NAME);
+    ESTACK_CHECK_NOW
+    estack_pop();
+}
+
 #ifdef FEAT_EVAL
 /*
  * Obtain a line when inside a ":while" or ":for" loop.
index 89653c77717a021535efe2f8fb077c37d756a22e..99951c81bf78727abc4fc128d7981dec3f7dd68b 100644 (file)
@@ -1822,6 +1822,13 @@ get_expr_indent(void)
     check_cursor();
     State = save_State;
 
+    // Reset did_throw, unless 'debug' has "throw" and inside a try/catch.
+    if (did_throw && (vim_strchr(p_debug, 't') == NULL || trylevel == 0))
+    {
+       handle_did_throw();
+       did_throw = FALSE;
+    }
+
     // If there is an error, just keep the current indent.
     if (indent < 0)
        indent = get_indent();
index 959f209ac17e28f2333709c5fe28a86add8dca94..d22d40689cc72ed59b2211d303c860af54c8ae7a 100644 (file)
@@ -3,6 +3,7 @@ void do_exmode(int improved);
 int do_cmdline_cmd(char_u *cmd);
 int do_cmd_argument(char_u *cmd);
 int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, int flags);
+void handle_did_throw(void);
 int getline_equal(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie, char_u *(*func)(int, void *, int, getline_opt_T));
 void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
 char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
index a2247dccab314359806dfd45f5d053c107f67b37..a3f1d12505f49084ef762c454bd0f6817f17aba0 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3259,
 /**/
     3258,
 /**/