Projects
Mega:23.03
vim
_service:tar_scm:backport-CVE-2022-2343.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-CVE-2022-2343.patch of Package vim
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2