CVE-2022-2343 (C, published 2022-07-08T18:15Z)
Description: value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0044.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: CWE-122 \u2014 Heap-based Buffer Overflow
A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
Repository: https://github.com/vim/vim
Files changed:
src/insexpand.c
src/testdir/test_ins_complete.vim
src/version.c
Commit message: 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.


Vulnerable code:
	int	actual_len,
	int	actual_compl_length,
	int	min_len)
    wca = ALLOC_MULT(int, actual_len);
    for (i = 0; i < actual_len; ++i)
		for (i = actual_compl_length; i < actual_len; ++i)
		for (i = actual_compl_length; i < actual_len; ++i)
    // 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.
    while (i < actual_len && (p - IObuff + 6) < IOSIZE)
	if (has_mbyte)
    *p = NUL;

    int		actual_len;		// Take multi-byte characters
    int		actual_compl_length;	// into account.
	    actual_len = 0;
		++actual_len;
	    actual_len = len;
	    actual_compl_length = 0;
		++actual_compl_length;
	    actual_compl_length = compl_length;
	// "actual_len" may be smaller than "actual_compl_length" when using
	min_len = actual_len < actual_compl_length
					   ? actual_len : actual_compl_length;
	str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
								min_len);
    return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);

Fixed code:
 * If the result is in allocated memory "tofree" is set to it.
	int	char_len,
	int	compl_char_len,
	int	min_len,
	char_u  **tofree)
    garray_T	gap;
    wca = ALLOC_MULT(int, char_len);
    for (i = 0; i < char_len; ++i)
		for (i = compl_char_len; i < char_len; ++i)
		for (i = compl_char_len; i < char_len; ++i)
    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)
    }
    if (gap.ga_data != NULL)
    {
	*tofree = gap.ga_data;
	return gap.ga_data;
    }

    *p = NUL;
    int		char_len;		// count multi-byte characters
    int		compl_char_len;
    int		res;
    char_u	*tofree = NULL;
	    char_len = 0;
		++char_len;
	    char_len = len;
	    compl_char_len = 0;
		++compl_char_len;
	    compl_char_len = compl_length;
	// "char_len" may be smaller than "compl_char_len" when using
	min_len = char_len < compl_char_len ? char_len : compl_char_len;
	str = ins_compl_infercase_gettext(str, char_len,
					  compl_char_len, min_len, &tofree);
    res = ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
    vim_free(tofree);
    return res;
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


/**/
    45,