From: Foxe Chen Date: Fri, 15 May 2026 16:00:04 +0000 (+0000) Subject: patch 9.2.0485: clipboard provider callback can be called recursively X-Git-Tag: v9.2.0485^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e85e3e5d8547cf83375fcb88803940e74df15bae;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 71585da898..2bcad93a39 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 e47c9a5adf..745a8c47a2 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 c3d98b96e3..e1afbfbe2c 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 2602bccd37..fa746a9ae6 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, /**/