patch 9.2.0485: clipboard provider callback can be called recursively
Commit:
https://github.com/vim/vim/commit/e85e3e5d8547cf83375fcb88803940e74df15bae
Author: Foxe Chen <[email protected]>
Date: Fri May 15 16:00:04 2026 +0000
patch 9.2.0485: clipboard provider callback can be called recursively
Problem: clipboard provider callback can be called recursively, leading
to E132: Function call depth is higher than 'maxfuncdepth'
Solution: Prevent recursive calls of
clip_provider_copy()/clip_provider_paste() (Foxe Chen).
closes: #20213
Signed-off-by: Foxe Chen <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 71585da89..2bcad93a3 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -5346,6 +5346,9 @@ a |lambda| expression.
With the exception of the "available" callback if a callback is not provided,
Vim will not invoke anything, and this is not an error.
+If the "paste" or "copy" callbacks are triggered recursively, then they will
+not be called.
+
*clipboard-providers-textlock*
In both the "paste" and "copy" callbacks, it is not allowed to change the
buffer text, see |textlock|.
diff --git a/src/clipboard.c b/src/clipboard.c
index e47c9a5ad..745a8c47a 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -3428,6 +3428,7 @@ clip_provider_get_callback(
static void
clip_provider_copy(char_u *reg, char_u *provider)
{
+ static bool recursive = false;
callback_T callback;
typval_T rettv;
typval_T argvars[4];
@@ -3435,6 +3436,9 @@ clip_provider_copy(char_u *reg, char_u *provider)
char_u type[2 + NUMBUFLEN] = {0};
list_T *list = NULL;
+ if (recursive)
+ return;
+
if (clip_provider_get_callback(
reg,
provider,
@@ -3497,7 +3501,9 @@ clip_provider_copy(char_u *reg, char_u *provider)
argvars[3].v_type = VAR_UNKNOWN;
textlock++;
+ recursive = true;
call_callback(&callback, -1, &rettv, 3, argvars);
+ recursive = false;
clear_tv(&rettv);
textlock--;
@@ -3508,6 +3514,7 @@ clip_provider_copy(char_u *reg, char_u *provider)
static void
clip_provider_paste(char_u *reg, char_u *provider)
{
+ static bool recursive = false;
callback_T callback;
typval_T argvars[2];
typval_T rettv;
@@ -3515,6 +3522,9 @@ clip_provider_paste(char_u *reg, char_u *provider)
char_u *reg_type;
list_T *lines;
+ if (recursive)
+ return;
+
if (clip_provider_get_callback(
reg,
provider,
@@ -3528,7 +3538,9 @@ clip_provider_paste(char_u *reg, char_u *provider)
argvars[1].v_type = VAR_UNKNOWN;
textlock++;
+ recursive = true;
ret = call_callback(&callback, -1, &rettv, 1, argvars);
+ recursive = false;
textlock--;
if (ret == FAIL)
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index c3d98b96e..e1afbfbe2 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -765,7 +765,10 @@ func s:Paste(reg)
else
return ("c", [])
endif
+ endif
+ if exists("g:vim_paste_recursive")
+ call getreg(a:reg)
endif
endfunc
@@ -773,6 +776,9 @@ func s:Copy(reg, type, lines)
if exists("g:vim_copy_count")
let g:vim_copy_count[a:reg] += 1
endif
+ if exists("g:vim_copy_recursive")
+ call setreg(a:reg, a:lines)
+ endif
let g:vim_copy = {
\ "reg": a:reg,
@@ -1349,4 +1355,34 @@ func Test_clipboard_provider_clipboard_option()
set clipboard&
endfunc
+" Test that callback aren't called recursively
+func Test_clipboard_provider_recursive()
+ let v:clipproviders["test"] = {
+ \ "paste": {
+ \ '+': function("s:Paste"),
+ \ '*': function("s:Paste")
+ \ },
+ \ "copy": {
+ \ '+': function("s:Copy"),
+ \ '*': function("s:Copy")
+ \ }
+ \ }
+ set clipmethod=test
+
+ let g:vim_paste = "count"
+ let g:vim_paste_count = {'*': 0, '+': 0}
+ let g:vim_copy_count = {'*': 0, '+': 0}
+ let g:vim_paste_recursive = 1
+ let g:vim_copy_recursive = 1
+
+ call getreg('+')
+ call assert_equal(1, g:vim_paste_count['+'])
+ call setreg('+', 'test')
+ call assert_equal(1, g:vim_copy_count['+'])
+
+ set clipmethod&
+ unlet g:vim_paste_recursive
+ unlet g:vim_copy_recursive
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 2602bccd3..fa746a9ae 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 485,
/**/
484,
/**/
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1wNvBo-006TRV-4o%40256bit.org.