fix CVE-2022-2343
(cherry picked from commit e025e5df622e2abf1925db04c63b09543c506b83)
This commit is contained in:
parent
0b1f5b7aca
commit
977c89645f
233
backport-CVE-2022-2343.patch
Normal file
233
backport-CVE-2022-2343.patch
Normal file
@ -0,0 +1,233 @@
|
||||
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 | 96 +++++++++++++++++++++++++++------------
|
||||
src/testdir/test_ins_complete.vim | 14 ++++++
|
||||
2 files changed, 81 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/src/insexpand.c b/src/insexpand.c
|
||||
index 3b4d530..e8ba82e 100644
|
||||
--- a/src/insexpand.c
|
||||
+++ b/src/insexpand.c
|
||||
@@ -408,29 +408,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;
|
||||
+ vim_memset(IObuff, NUL, IOSIZE * sizeof(char_u));
|
||||
|
||||
// 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
|
||||
@@ -450,7 +453,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;
|
||||
}
|
||||
@@ -471,7 +474,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;
|
||||
}
|
||||
@@ -494,20 +497,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;
|
||||
}
|
||||
|
||||
@@ -528,10 +563,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)
|
||||
{
|
||||
@@ -541,44 +578,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, dir, flags, FALSE);
|
||||
+ res = ins_compl_add(str, len, fname, 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 b7cfd29..aa054f2 100644
|
||||
--- a/src/testdir/test_ins_complete.vim
|
||||
+++ b/src/testdir/test_ins_complete.vim
|
||||
@@ -397,3 +397,17 @@ func Test_complete_overrun()
|
||||
bwipe!
|
||||
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
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
@ -0,0 +1,239 @@
|
||||
From 6ad84ab3e48d9490e4139df04f2c55b136f5501d Mon Sep 17 00:00:00 2001
|
||||
From: Yegappan Lakshmanan <yegappan@yahoo.com>
|
||||
Date: Fri, 31 Dec 2021 12:59:53 +0000
|
||||
Subject: [PATCH] patch 8.2.3953: insert completion code is too complicated
|
||||
|
||||
Problem: Insert completion code is too complicated.
|
||||
Solution: More refactoring. Move function arguments into a struct.
|
||||
(Yegappan Lakshmanan, closes #9437)
|
||||
---
|
||||
src/insexpand.c | 196 +++++++++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 107 insertions(+), 89 deletions(-)
|
||||
|
||||
diff --git a/src/insexpand.c b/src/insexpand.c
|
||||
index 66a836e..3b4d530 100644
|
||||
--- a/src/insexpand.c
|
||||
+++ b/src/insexpand.c
|
||||
@@ -407,6 +407,111 @@ ins_compl_accept_char(int c)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Get the completed text by inferring the case of the originally typed text.
|
||||
+ */
|
||||
+ static char_u *
|
||||
+ins_compl_infercase_gettext(
|
||||
+ char_u *str,
|
||||
+ int actual_len,
|
||||
+ int actual_compl_length,
|
||||
+ int min_len)
|
||||
+{
|
||||
+ int *wca; // Wide character array.
|
||||
+ char_u *p;
|
||||
+ int i, c;
|
||||
+ int has_lower = FALSE;
|
||||
+ int was_letter = FALSE;
|
||||
+
|
||||
+ IObuff[0] = NUL;
|
||||
+
|
||||
+ // Allocate wide character array for the completion and fill it.
|
||||
+ wca = ALLOC_MULT(int, actual_len);
|
||||
+ if (wca == NULL)
|
||||
+ return IObuff;
|
||||
+
|
||||
+ p = str;
|
||||
+ for (i = 0; i < actual_len; ++i)
|
||||
+ if (has_mbyte)
|
||||
+ wca[i] = mb_ptr2char_adv(&p);
|
||||
+ else
|
||||
+ wca[i] = *(p++);
|
||||
+
|
||||
+ // Rule 1: Were any chars converted to lower?
|
||||
+ p = compl_orig_text;
|
||||
+ for (i = 0; i < min_len; ++i)
|
||||
+ {
|
||||
+ if (has_mbyte)
|
||||
+ c = mb_ptr2char_adv(&p);
|
||||
+ else
|
||||
+ c = *(p++);
|
||||
+ if (MB_ISLOWER(c))
|
||||
+ {
|
||||
+ has_lower = TRUE;
|
||||
+ if (MB_ISUPPER(wca[i]))
|
||||
+ {
|
||||
+ // Rule 1 is satisfied.
|
||||
+ for (i = actual_compl_length; i < actual_len; ++i)
|
||||
+ wca[i] = MB_TOLOWER(wca[i]);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Rule 2: No lower case, 2nd consecutive letter converted to
|
||||
+ // upper case.
|
||||
+ if (!has_lower)
|
||||
+ {
|
||||
+ p = compl_orig_text;
|
||||
+ for (i = 0; i < min_len; ++i)
|
||||
+ {
|
||||
+ if (has_mbyte)
|
||||
+ c = mb_ptr2char_adv(&p);
|
||||
+ else
|
||||
+ c = *(p++);
|
||||
+ if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
|
||||
+ {
|
||||
+ // Rule 2 is satisfied.
|
||||
+ for (i = actual_compl_length; i < actual_len; ++i)
|
||||
+ wca[i] = MB_TOUPPER(wca[i]);
|
||||
+ break;
|
||||
+ }
|
||||
+ was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Copy the original case of the part we typed.
|
||||
+ p = compl_orig_text;
|
||||
+ for (i = 0; i < min_len; ++i)
|
||||
+ {
|
||||
+ if (has_mbyte)
|
||||
+ c = mb_ptr2char_adv(&p);
|
||||
+ else
|
||||
+ c = *(p++);
|
||||
+ if (MB_ISLOWER(c))
|
||||
+ wca[i] = MB_TOLOWER(wca[i]);
|
||||
+ else if (MB_ISUPPER(c))
|
||||
+ wca[i] = MB_TOUPPER(wca[i]);
|
||||
+ }
|
||||
+
|
||||
+ // 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)
|
||||
+ p += (*mb_char2bytes)(wca[i++], p);
|
||||
+ else
|
||||
+ *(p++) = wca[i++];
|
||||
+ *p = NUL;
|
||||
+
|
||||
+ vim_free(wca);
|
||||
+
|
||||
+ return IObuff;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
|
||||
* case of the originally typed text is used, and the case of the completed
|
||||
* text is inferred, ie this tries to work out what case you probably wanted
|
||||
@@ -423,13 +528,9 @@ ins_compl_add_infercase(
|
||||
{
|
||||
char_u *str = str_arg;
|
||||
char_u *p;
|
||||
- int i, c;
|
||||
int actual_len; // Take multi-byte characters
|
||||
int actual_compl_length; // into account.
|
||||
int min_len;
|
||||
- int *wca; // Wide character array.
|
||||
- int has_lower = FALSE;
|
||||
- int was_letter = FALSE;
|
||||
int flags = 0;
|
||||
|
||||
if (p_ic && curbuf->b_p_inf && len > 0)
|
||||
@@ -469,91 +570,8 @@ ins_compl_add_infercase(
|
||||
min_len = actual_len < actual_compl_length
|
||||
? actual_len : actual_compl_length;
|
||||
|
||||
- // Allocate wide character array for the completion and fill it.
|
||||
- wca = ALLOC_MULT(int, actual_len);
|
||||
- if (wca != NULL)
|
||||
- {
|
||||
- p = str;
|
||||
- for (i = 0; i < actual_len; ++i)
|
||||
- if (has_mbyte)
|
||||
- wca[i] = mb_ptr2char_adv(&p);
|
||||
- else
|
||||
- wca[i] = *(p++);
|
||||
-
|
||||
- // Rule 1: Were any chars converted to lower?
|
||||
- p = compl_orig_text;
|
||||
- for (i = 0; i < min_len; ++i)
|
||||
- {
|
||||
- if (has_mbyte)
|
||||
- c = mb_ptr2char_adv(&p);
|
||||
- else
|
||||
- c = *(p++);
|
||||
- if (MB_ISLOWER(c))
|
||||
- {
|
||||
- has_lower = TRUE;
|
||||
- if (MB_ISUPPER(wca[i]))
|
||||
- {
|
||||
- // Rule 1 is satisfied.
|
||||
- for (i = actual_compl_length; i < actual_len; ++i)
|
||||
- wca[i] = MB_TOLOWER(wca[i]);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Rule 2: No lower case, 2nd consecutive letter converted to
|
||||
- // upper case.
|
||||
- if (!has_lower)
|
||||
- {
|
||||
- p = compl_orig_text;
|
||||
- for (i = 0; i < min_len; ++i)
|
||||
- {
|
||||
- if (has_mbyte)
|
||||
- c = mb_ptr2char_adv(&p);
|
||||
- else
|
||||
- c = *(p++);
|
||||
- if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
|
||||
- {
|
||||
- // Rule 2 is satisfied.
|
||||
- for (i = actual_compl_length; i < actual_len; ++i)
|
||||
- wca[i] = MB_TOUPPER(wca[i]);
|
||||
- break;
|
||||
- }
|
||||
- was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Copy the original case of the part we typed.
|
||||
- p = compl_orig_text;
|
||||
- for (i = 0; i < min_len; ++i)
|
||||
- {
|
||||
- if (has_mbyte)
|
||||
- c = mb_ptr2char_adv(&p);
|
||||
- else
|
||||
- c = *(p++);
|
||||
- if (MB_ISLOWER(c))
|
||||
- wca[i] = MB_TOLOWER(wca[i]);
|
||||
- else if (MB_ISUPPER(c))
|
||||
- wca[i] = MB_TOUPPER(wca[i]);
|
||||
- }
|
||||
-
|
||||
- // 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)
|
||||
- p += (*mb_char2bytes)(wca[i++], p);
|
||||
- else
|
||||
- *(p++) = wca[i++];
|
||||
- *p = NUL;
|
||||
-
|
||||
- vim_free(wca);
|
||||
- }
|
||||
-
|
||||
- str = IObuff;
|
||||
+ str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
|
||||
+ min_len);
|
||||
}
|
||||
if (cont_s_ipos)
|
||||
flags |= CP_CONT_S_IPOS;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
10
vim.spec
10
vim.spec
@ -12,7 +12,7 @@
|
||||
Name: vim
|
||||
Epoch: 2
|
||||
Version: 8.2
|
||||
Release: 53
|
||||
Release: 54
|
||||
Summary: Vim is a highly configurable text editor for efficiently creating and changing any kind of text.
|
||||
License: Vim and MIT
|
||||
URL: http://www.vim.org
|
||||
@ -155,6 +155,8 @@ Patch6118: backport-CVE-2022-2287.patch
|
||||
Patch6119: backport-patch-9.0.0022-spell-test-fails.patch
|
||||
Patch6120: backport-CVE-2022-2210.patch
|
||||
Patch6121: backport-CVE-2022-2289.patch
|
||||
Patch6122: backport-patch-8.2.3953-insert-completion-code-is-too-complic.patch
|
||||
Patch6123: backport-CVE-2022-2343.patch
|
||||
|
||||
Patch9000: bugfix-rm-modify-info-version.patch
|
||||
|
||||
@ -543,6 +545,12 @@ popd
|
||||
%{_mandir}/man1/evim.*
|
||||
|
||||
%changelog
|
||||
* Wed Jul 20 2022 shixuantong <shixuantong@h-partners.com> - 2:8.2-54
|
||||
- Type:CVE
|
||||
- ID:CVE-2022-2343
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2022-2343
|
||||
|
||||
* Fri Jul 15 2022 shangyibin <shangyibin1@h-partners.com> - 2:8.2-53
|
||||
- Type:CVE
|
||||
- ID:CVE-2022-2289
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user