]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1462: recursively calling :defer function if it does :qa v9.0.1462
authorBram Moolenaar <Bram@vim.org>
Mon, 17 Apr 2023 18:23:45 +0000 (19:23 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 17 Apr 2023 18:23:45 +0000 (19:23 +0100)
Problem:    Recursively calling :defer function if it does :qa.
Solution:   Clear the defer entry before calling the function. (closes #12266)

src/testdir/test_user_func.vim
src/userfunc.c
src/version.c

index ade259cffaa4223235b6bb6f73b2599c345f5305..8715a0b78a7c6d77dd67e545af10ce3cde95d61f 100644 (file)
@@ -656,6 +656,7 @@ func Test_defer_quitall()
       vim9script
       func DeferLevelTwo()
         call writefile(['text'], 'XQuitallTwo', 'D')
+        call writefile(['quit'], 'XQuitallThree', 'a')
         qa!
       endfunc
 
@@ -671,6 +672,9 @@ func Test_defer_quitall()
   call assert_equal(0, v:shell_error)
   call assert_false(filereadable('XQuitallOne'))
   call assert_false(filereadable('XQuitallTwo'))
+  call assert_equal(['quit'], readfile('XQuitallThree'))
+
+  call delete('XQuitallThree')
 endfunc
 
 func Test_defer_quitall_in_expr_func()
index 25f76ecb0ed9a2642dfb3f54b564ad17541b2ef9..a506d72c894c87f18642c9b9b73e24eb1a6d2baa 100644 (file)
@@ -6096,20 +6096,27 @@ handle_defer_one(funccall_T *funccal)
 
     for (idx = funccal->fc_defer.ga_len - 1; idx >= 0; --idx)
     {
-       funcexe_T   funcexe;
-       typval_T    rettv;
        defer_T     *dr = ((defer_T *)funccal->fc_defer.ga_data) + idx;
-       int         i;
 
+       if (dr->dr_name == NULL)
+           // already being called, can happen if function does ":qa"
+           continue;
+
+       funcexe_T   funcexe;
        CLEAR_FIELD(funcexe);
        funcexe.fe_evaluate = TRUE;
 
+       typval_T    rettv;
        rettv.v_type = VAR_UNKNOWN;     // clear_tv() uses this
-       call_func(dr->dr_name, -1, &rettv,
-                                   dr->dr_argcount, dr->dr_argvars, &funcexe);
+
+       char_u *name = dr->dr_name;
+       dr->dr_name = NULL;
+
+       call_func(name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe);
+
        clear_tv(&rettv);
-       vim_free(dr->dr_name);
-       for (i = dr->dr_argcount - 1; i >= 0; --i)
+       vim_free(name);
+       for (int i = dr->dr_argcount - 1; i >= 0; --i)
            clear_tv(&dr->dr_argvars[i]);
     }
     ga_clear(&funccal->fc_defer);
index 053fe7827897608b4f51110a45de54645e85447a..6dc7e34313fd7dc1e8c3bf54a86881936aedf4a5 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1462,
 /**/
     1461,
 /**/