Fetch the repository succeeded.
This action will force synchronization from src-openEuler/vim, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
FROM CAEA66442D86E7BBBA3BF3DC202C3C0D549B9853 MON SEP 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Thu, 7 Jul 2022 19:42:04 +0100
Subject: [PATCH] patch 9.0.0045: reading past end of completion with a
long line
Problem: Reading past end of completion with a long line and 'infercase'
set.
Solution: Allocate the string if needed.
---
src/insexpand.c | 94 ++++++++++++++++++++++---------
src/testdir/test_ins_complete.vim | 16 ++++++
2 files changed, 82 insertions(+), 28 deletions(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index 734550f..0ecb656 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -524,29 +524,32 @@ ins_compl_accept_char(int c)
/*
* Get the completed text by inferring the case of the originally typed text.
+ * If the result is in allocated memory "tofree" is set to it.
*/
static char_u *
ins_compl_infercase_gettext(
char_u *str,
- int actual_len,
- int actual_compl_length,
- int min_len)
+ int char_len,
+ int compl_char_len,
+ int min_len,
+ char_u **tofree)
{
int *wca; // Wide character array.
char_u *p;
int i, c;
int has_lower = FALSE;
int was_letter = FALSE;
+ garray_T gap;
IObuff[0] = NUL;
// Allocate wide character array for the completion and fill it.
- wca = ALLOC_MULT(int, actual_len);
+ wca = ALLOC_MULT(int, char_len);
if (wca == NULL)
return IObuff;
p = str;
- for (i = 0; i < actual_len; ++i)
+ for (i = 0; i < char_len; ++i)
if (has_mbyte)
wca[i] = mb_ptr2char_adv(&p);
else
@@ -566,7 +569,7 @@ ins_compl_infercase_gettext(
if (MB_ISUPPER(wca[i]))
{
// Rule 1 is satisfied.
- for (i = actual_compl_length; i < actual_len; ++i)
+ for (i = compl_char_len; i < char_len; ++i)
wca[i] = MB_TOLOWER(wca[i]);
break;
}
@@ -587,7 +590,7 @@ ins_compl_infercase_gettext(
if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
{
// Rule 2 is satisfied.
- for (i = actual_compl_length; i < actual_len; ++i)
+ for (i = compl_char_len; i < char_len; ++i)
wca[i] = MB_TOUPPER(wca[i]);
break;
}
@@ -610,20 +613,52 @@ ins_compl_infercase_gettext(
}
// Generate encoding specific output from wide character array.
- // Multi-byte characters can occupy up to five bytes more than
- // ASCII characters, and we also need one byte for NUL, so stay
- // six bytes away from the edge of IObuff.
p = IObuff;
i = 0;
- while (i < actual_len && (p - IObuff + 6) < IOSIZE)
- if (has_mbyte)
+ ga_init2(&gap, 1, 500);
+ while (i < char_len)
+ {
+ if (gap.ga_data != NULL)
+ {
+ if (ga_grow(&gap, 10) == FAIL)
+ {
+ ga_clear(&gap);
+ return (char_u *)"[failed]";
+ }
+ p = (char_u *)gap.ga_data + gap.ga_len;
+ if (has_mbyte)
+ gap.ga_len += (*mb_char2bytes)(wca[i++], p);
+ else
+ {
+ *p = wca[i++];
+ ++gap.ga_len;
+ }
+ }
+ else if ((p - IObuff) + 6 >= IOSIZE)
+ {
+ // Multi-byte characters can occupy up to five bytes more than
+ // ASCII characters, and we also need one byte for NUL, so when
+ // getting to six bytes from the edge of IObuff switch to using a
+ // growarray. Add the character in the next round.
+ if (ga_grow(&gap, IOSIZE) == FAIL)
+ return (char_u *)"[failed]";
+ STRCPY(gap.ga_data, IObuff);
+ gap.ga_len = STRLEN(IObuff);
+ }
+ else if (has_mbyte)
p += (*mb_char2bytes)(wca[i++], p);
else
*(p++) = wca[i++];
- *p = NUL;
-
+ }
vim_free(wca);
+ if (gap.ga_data != NULL)
+ {
+ *tofree = gap.ga_data;
+ return gap.ga_data;
+ }
+
+ *p = NUL;
return IObuff;
}
@@ -644,10 +679,12 @@ ins_compl_add_infercase(
{
char_u *str = str_arg;
char_u *p;
- int actual_len; // Take multi-byte characters
- int actual_compl_length; // into account.
+ int char_len; // count multi-byte characters
+ int compl_char_len;
int min_len;
int flags = 0;
+ int res;
+ char_u *tofree = NULL;
if (p_ic && curbuf->b_p_inf && len > 0)
{
@@ -657,44 +694,45 @@ ins_compl_add_infercase(
if (has_mbyte)
{
p = str;
- actual_len = 0;
+ char_len = 0;
while (*p != NUL)
{
MB_PTR_ADV(p);
- ++actual_len;
+ ++char_len;
}
}
else
- actual_len = len;
+ char_len = len;
// Find actual length of original text.
if (has_mbyte)
{
p = compl_orig_text;
- actual_compl_length = 0;
+ compl_char_len = 0;
while (*p != NUL)
{
MB_PTR_ADV(p);
- ++actual_compl_length;
+ ++compl_char_len;
}
}
else
- actual_compl_length = compl_length;
+ compl_char_len = compl_length;
- // "actual_len" may be smaller than "actual_compl_length" when using
+ // "char_len" may be smaller than "compl_char_len" when using
// thesaurus, only use the minimum when comparing.
- min_len = actual_len < actual_compl_length
- ? actual_len : actual_compl_length;
+ min_len = char_len < compl_char_len ? char_len : compl_char_len;
- str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
- min_len);
+ str = ins_compl_infercase_gettext(str, char_len,
+ compl_char_len, min_len, &tofree);
}
if (cont_s_ipos)
flags |= CP_CONT_S_IPOS;
if (icase)
flags |= CP_ICASE;
- return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
+ res = ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
+ vim_free(tofree);
+ return res;
}
/*
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 20c2b4f..f2daa02 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2192,4 +2192,20 @@ func Test_complete_overrun()
endfunc
+func Test_infercase_very_long_line()
+ " this was truncating the line when inferring case
+ new
+ let longLine = "blah "->repeat(300)
+ let verylongLine = "blah "->repeat(400)
+ call setline(1, verylongLine)
+ call setline(2, longLine)
+ set ic infercase
+ exe "normal 2Go\<C-X>\<C-L>\<Esc>"
+ call assert_equal(longLine, getline(3))
+
+ bwipe!
+ set noic noinfercase
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
--
2.36.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。