CVE-2022-2980 (C, published 2022-08-25T20:15Z)
Description: value: NULL Pointer Dereference in GitHub repository vim/vim prior to 9.0.0259.
Severity: nan (CVSS v3 base score: 5.5)
Weakness: CWE-476 \u2014 NULL Pointer Dereference
The product dereferences a pointer that it expects to be valid but is NULL.
Repository: https://github.com/vim/vim
Files changed:
src/mouse.c
src/testdir/test_tabline.vim
src/version.c
Commit message: patch 9.0.0259: crash with mouse click when not initialized

Problem:    Crash with mouse click when not initialized.
Solution:   Check TabPageIdxs[] is not NULL.


Vulnerable code:
    // Check for clicking in the tab page line.
    if (mouse_row == 0 && firstwin->w_winrow > 0)
	if (is_drag)
	    if (in_tab_line)
		c1 = TabPageIdxs[mouse_col];
		tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
								? c1 - 1 : c1);
	    return FALSE;
	}
	// click in a tab selects that tab page
	if (is_click
		&& cmdwin_type == 0
		&& mouse_col < Columns)
	{
	    in_tab_line = TRUE;
	    c1 = TabPageIdxs[mouse_col];
	    if (c1 >= 0)
		if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
		{
		    // double click opens new page
		    end_visual_mode_keep_button();
		    tabpage_new();
		    tabpage_move(c1 == 0 ? 9999 : c1 - 1);
		}
		else
		    // Go to specified tab page, or next one if not clicking
		    // on a label.
		    goto_tabpage(c1);

		    // It's like clicking on the status line of a window.
		    if (curwin != old_curwin)
		}
	    }
	    else
	    {
		tabpage_T	*tp;
		// Close the current or specified tab page.
		if (c1 == -999)
		    tp = curtab;
		    tp = find_tabpage(-c1);
		if (tp == curtab)
		    if (first_tabpage->tp_next != NULL)
			tabpage_close(FALSE);
		else if (tp != NULL)
		    tabpage_close_other(tp, FALSE);
	return TRUE;
    }
    else if (is_drag && in_tab_line)
    {
	c1 = TabPageIdxs[mouse_col];
	tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
	return FALSE;

Fixed code:
    if (TabPageIdxs != NULL)  // only when initialized
	// Check for clicking in the tab page line.
	if (mouse_row == 0 && firstwin->w_winrow > 0)
	    if (is_drag)
		if (in_tab_line)
		{
		    c1 = TabPageIdxs[mouse_col];
		    tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
								    ? c1 - 1 : c1);
		}
		return FALSE;
	    // click in a tab selects that tab page
	    if (is_click
		    && cmdwin_type == 0
		    && mouse_col < Columns)
		in_tab_line = TRUE;
		c1 = TabPageIdxs[mouse_col];
		if (c1 >= 0)
		    if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
		    {
			// double click opens new page
			tabpage_new();
			tabpage_move(c1 == 0 ? 9999 : c1 - 1);
		    }
		    else
		    {
			// Go to specified tab page, or next one if not clicking
			// on a label.
			goto_tabpage(c1);
			// It's like clicking on the status line of a window.
			if (curwin != old_curwin)
			    end_visual_mode_keep_button();
		    }
		}
		    tabpage_T	*tp;

		    // Close the current or specified tab page.
		    if (c1 == -999)
			tp = curtab;
		    else
			tp = find_tabpage(-c1);
		    if (tp == curtab)
		    {
			if (first_tabpage->tp_next != NULL)
			    tabpage_close(FALSE);
		    }
		    else if (tp != NULL)
			tabpage_close_other(tp, FALSE);
	    return TRUE;
	}
	else if (is_drag && in_tab_line)
	{
	    c1 = TabPageIdxs[mouse_col];
	    tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
	    return FALSE;
func Test_mouse_click_in_tab()
  " This used to crash because TabPageIdxs[] was not initialized
  let lines =<< trim END
      tabnew
      set mouse=a
      exe "norm \<LeftMouse>"
  END
  call writefile(lines, 'Xclickscript')
  call RunVim([], [], "-e -s -S Xclickscript -c qa")

  call delete('Xclickscript')
endfunc


/**/
    259,