From 8b4ef1f18b20988fac00a26bc4277cd9cc62f272 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sun, 25 Oct 2026 17:31:21 +0000 Subject: [PATCH] patch 9.2.1240: crash when a clipboard provider returns a null tuple Problem: Crash when the "paste" callback of a clipboard provider returns a null tuple or a null list. Solution: Check for a NULL tuple and a NULL list before using the returned value (Yegappan Lakshmanan). fixes: #21583 closes: #21584 Assisted-by: Claude Code (Claude Opus 5.5) Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/clipboard.c | 2 ++ src/testdir/test_registers.vim | 32 ++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 36 insertions(+) diff --git a/src/clipboard.c b/src/clipboard.c index 0c3d12534d..e175ae71a0 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -3540,6 +3540,7 @@ clip_provider_paste(char_u *reg, char_u *provider) if (ret == FAIL) goto exit; else if (rettv.v_type == VAR_TUPLE + && rettv.vval.v_tuple != NULL && TUPLE_LEN(rettv.vval.v_tuple) == 2 && TUPLE_ITEM(rettv.vval.v_tuple, 0)->v_type == VAR_STRING && TUPLE_ITEM(rettv.vval.v_tuple, 1)->v_type == VAR_LIST) @@ -3548,6 +3549,7 @@ clip_provider_paste(char_u *reg, char_u *provider) lines = TUPLE_ITEM(rettv.vval.v_tuple, 1)->vval.v_list; } else if (rettv.v_type == VAR_LIST + && rettv.vval.v_list != NULL && rettv.vval.v_list->lv_len == 2 && rettv.vval.v_list->lv_first->li_tv.v_type == VAR_STRING && rettv.vval.v_list->lv_first->li_next->li_tv.v_type == VAR_LIST) diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index 9413b6ca09..9bd8ecb553 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -1358,4 +1358,36 @@ func Test_writing_readonly_regs() call assert_fails('let @~ = "foo"', 'E354:') endfunc +func s:ProviderPaste(reg) + return g:provider_paste_ret +endfunc + +" A clipboard provider "paste" callback returning a null tuple or a null list +" used to cause a crash. The register should not change. +func Test_clipboard_provider_paste_null_value() + CheckFeature clipboard_provider + + let v:clipproviders['Xnull'] = { + \ 'paste': {'+': function('s:ProviderPaste'), + \ '*': function('s:ProviderPaste')}} + set clipmethod=Xnull + + try + let g:provider_paste_ret = ('', ['one', 'two']) + call assert_equal(['one', 'two'], getreg('+', 1, 1)) + let g:provider_paste_ret = test_null_tuple() + call assert_equal(['one', 'two'], getreg('+', 1, 1)) + let g:provider_paste_ret = test_null_list() + call assert_equal(['one', 'two'], getreg('+', 1, 1)) + + finally + call remove(v:clipproviders, 'Xnull') + unlet g:provider_paste_ret + call setreg('"', []) + call setreg('+', []) + call setreg('*', []) + set clipmethod& + endtry +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index b58937ab7f..a42eb80c8b 100644 --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1240, /**/ 1239, /**/