mirror of
https://github.com/neovim/neovim.git
synced 2026-05-23 21:30:11 +00:00
fix(move): avoid integer overflow with large 'scrolloff' (#39251)
This commit is contained in:
@@ -439,7 +439,7 @@ bool set_leftcol(colnr_T leftcol)
|
||||
bool retval = false;
|
||||
// If the cursor is right or left of the screen, move it to last or first
|
||||
// visible character.
|
||||
int siso = get_sidescrolloff_value(curwin);
|
||||
int64_t siso = get_sidescrolloff_value(curwin);
|
||||
if (curwin->w_virtcol > (colnr_T)(lastcol - siso)) {
|
||||
retval = true;
|
||||
coladvance(curwin, (colnr_T)(lastcol - siso));
|
||||
|
||||
@@ -6259,7 +6259,7 @@ static void ex_syncbind(exarg_T *eap)
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_p_scb && wp->w_buffer) {
|
||||
linenr_T y = plines_m_win_fill(wp, 1, wp->w_buffer->b_ml.ml_line_count)
|
||||
- get_scrolloff_value(curwin);
|
||||
- (int)get_scrolloff_value(curwin);
|
||||
vtopline = MIN(vtopline, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ void update_topline(win_T *wp)
|
||||
}
|
||||
}
|
||||
if (check_botline) {
|
||||
int n = 0;
|
||||
int64_t n = 0;
|
||||
if (win_lines_concealed(wp)) {
|
||||
// Count the number of logical lines between the cursor and
|
||||
// botline - p_so (approximation of how much will be
|
||||
@@ -421,7 +421,7 @@ void update_topline(win_T *wp)
|
||||
hasFolding(wp, lnum, &lnum, NULL);
|
||||
}
|
||||
} else {
|
||||
n = wp->w_cursor.lnum - wp->w_botline + 1 + (int)(*so_ptr);
|
||||
n = wp->w_cursor.lnum - wp->w_botline + 1 + *so_ptr;
|
||||
}
|
||||
if (n <= wp->w_view_height + 1) {
|
||||
scroll_cursor_bot(wp, scrolljump_value(wp), false);
|
||||
@@ -469,7 +469,7 @@ static int scrolljump_value(win_T *wp)
|
||||
/// Return true when there are not 'scrolloff' lines above the cursor for window "wp".
|
||||
static bool check_top_offset(win_T *wp)
|
||||
{
|
||||
int so = get_scrolloff_value(wp);
|
||||
int64_t so = get_scrolloff_value(wp);
|
||||
if (wp->w_cursor.lnum < wp->w_topline + so || win_lines_concealed(wp)) {
|
||||
lineoff_T loff;
|
||||
loff.lnum = wp->w_cursor.lnum;
|
||||
@@ -888,11 +888,11 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
// If Cursor is right of the screen, scroll leftwards
|
||||
// If we get closer to the edge than 'sidescrolloff', scroll a little
|
||||
// extra
|
||||
int siso = get_sidescrolloff_value(wp);
|
||||
int off_left = startcol - wp->w_leftcol - siso;
|
||||
int off_right = endcol - wp->w_leftcol - wp->w_view_width + siso + 1;
|
||||
int64_t siso = get_sidescrolloff_value(wp);
|
||||
int64_t off_left = startcol - wp->w_leftcol - siso;
|
||||
int64_t off_right = endcol - wp->w_leftcol - (wp->w_view_width - siso) + 1;
|
||||
if (off_left < 0 || off_right > 0) {
|
||||
int diff = (off_left < 0) ? -off_left : off_right;
|
||||
int64_t diff = (off_left < 0) ? -off_left : off_right;
|
||||
|
||||
// When far off or not enough room on either side, put cursor in
|
||||
// middle of window.
|
||||
@@ -902,12 +902,12 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
} else {
|
||||
if (diff < p_ss) {
|
||||
assert(p_ss <= INT_MAX);
|
||||
diff = (int)p_ss;
|
||||
diff = p_ss;
|
||||
}
|
||||
if (off_left < 0) {
|
||||
new_leftcol = wp->w_leftcol - diff;
|
||||
new_leftcol = wp->w_leftcol - (int)diff;
|
||||
} else {
|
||||
new_leftcol = wp->w_leftcol + diff;
|
||||
new_leftcol = wp->w_leftcol + (int)diff;
|
||||
}
|
||||
}
|
||||
new_leftcol = MAX(new_leftcol, 0);
|
||||
@@ -934,7 +934,7 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
}
|
||||
|
||||
int plines = 0;
|
||||
int so = get_scrolloff_value(wp);
|
||||
int64_t so = get_scrolloff_value(wp);
|
||||
colnr_T prev_skipcol = wp->w_skipcol;
|
||||
if ((wp->w_wrow >= wp->w_view_height
|
||||
|| ((prev_skipcol > 0
|
||||
@@ -962,8 +962,8 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
}
|
||||
plines--;
|
||||
if (plines > wp->w_wrow + so) {
|
||||
assert(so <= INT_MAX);
|
||||
n = wp->w_wrow + so;
|
||||
assert(wp->w_wrow + so <= INT_MAX);
|
||||
n = (int)(wp->w_wrow + so);
|
||||
} else {
|
||||
n = plines;
|
||||
}
|
||||
@@ -988,7 +988,8 @@ void curs_columns(win_T *wp, int may_scroll)
|
||||
} else if (extra == 1) {
|
||||
// less than 'scrolloff' lines above, decrease skipcol
|
||||
assert(so <= INT_MAX);
|
||||
extra = (wp->w_skipcol + so * width2 - wp->w_virtcol + width2 - 1) / width2;
|
||||
extra = (int)((wp->w_skipcol + so * width2 - wp->w_virtcol
|
||||
+ width2 - 1) / width2);
|
||||
if (extra > 0) {
|
||||
if ((colnr_T)(extra * width2) > wp->w_skipcol) {
|
||||
extra = wp->w_skipcol / width2;
|
||||
@@ -1212,10 +1213,10 @@ static void cursor_correct_sms(win_T *wp)
|
||||
return;
|
||||
}
|
||||
|
||||
int so = get_scrolloff_value(wp);
|
||||
int64_t so = get_scrolloff_value(wp);
|
||||
int width1 = wp->w_view_width - win_col_off(wp);
|
||||
int width2 = width1 + win_col_off2(wp);
|
||||
int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||
int64_t so_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||
int space_cols = (wp->w_view_height - 1) * width2;
|
||||
int size = so == 0 ? 0 : linetabsize_eol(wp, wp->w_topline);
|
||||
|
||||
@@ -1236,8 +1237,8 @@ static void cursor_correct_sms(win_T *wp)
|
||||
int overlap = wp->w_skipcol == 0
|
||||
? 0 : sms_marker_overlap(wp, wp->w_view_width - width2);
|
||||
// If we have non-zero scrolloff, ignore marker overlap.
|
||||
int top = wp->w_skipcol + (so_cols != 0 ? so_cols : overlap);
|
||||
int bot = wp->w_skipcol + width1 + (wp->w_view_height - 1) * width2 - so_cols;
|
||||
int64_t top = wp->w_skipcol + (so_cols != 0 ? so_cols : overlap);
|
||||
int64_t bot = wp->w_skipcol + width1 + (wp->w_view_height - 1) * width2 - so_cols;
|
||||
|
||||
validate_virtcol(wp);
|
||||
colnr_T col = wp->w_virtcol;
|
||||
@@ -1564,8 +1565,8 @@ void adjust_skipcol(void)
|
||||
return; // no text will be displayed
|
||||
}
|
||||
int width2 = width1 + win_col_off2(curwin);
|
||||
int so = get_scrolloff_value(curwin);
|
||||
colnr_T scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||
int64_t so = get_scrolloff_value(curwin);
|
||||
int64_t scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2;
|
||||
bool scrolled = false;
|
||||
|
||||
validate_cheight(curwin);
|
||||
@@ -1596,7 +1597,7 @@ void adjust_skipcol(void)
|
||||
return; // don't scroll in the other direction now
|
||||
}
|
||||
int row = 0;
|
||||
colnr_T col = curwin->w_virtcol + scrolloff_cols;
|
||||
int64_t col = curwin->w_virtcol + scrolloff_cols;
|
||||
|
||||
// Avoid adjusting for 'scrolloff' beyond the text line height.
|
||||
if (scrolloff_cols > 0) {
|
||||
@@ -1613,7 +1614,7 @@ void adjust_skipcol(void)
|
||||
row++;
|
||||
}
|
||||
if (col > width2) {
|
||||
row += (int)col / width2;
|
||||
row += (int)(col / width2);
|
||||
}
|
||||
if (row >= curwin->w_view_height) {
|
||||
if (curwin->w_skipcol == 0) {
|
||||
@@ -1785,7 +1786,7 @@ void scroll_cursor_top(win_T *wp, int min_scroll, int always)
|
||||
linenr_T old_topline = wp->w_topline;
|
||||
int old_skipcol = wp->w_skipcol;
|
||||
linenr_T old_topfill = wp->w_topfill;
|
||||
int off = get_scrolloff_value(wp);
|
||||
int64_t off = get_scrolloff_value(wp);
|
||||
|
||||
if (mouse_dragging > 0) {
|
||||
off = mouse_dragging - 1;
|
||||
@@ -1861,7 +1862,7 @@ void scroll_cursor_top(win_T *wp, int min_scroll, int always)
|
||||
wp->w_topline = MIN(wp->w_topline, wp->w_cursor.lnum);
|
||||
wp->w_topfill = win_get_fill(wp, wp->w_topline);
|
||||
if (wp->w_topfill > 0 && extra > off) {
|
||||
wp->w_topfill -= extra - off;
|
||||
wp->w_topfill -= extra - (int)off;
|
||||
wp->w_topfill = MAX(wp->w_topfill, 0);
|
||||
}
|
||||
check_topfill(wp, false);
|
||||
@@ -2027,7 +2028,7 @@ void scroll_cursor_bot(win_T *wp, int min_scroll, bool set_topbot)
|
||||
int fill_below_window = win_get_fill(wp, wp->w_botline) - wp->w_filler_rows;
|
||||
|
||||
int extra = 0;
|
||||
int so = get_scrolloff_value(wp);
|
||||
int64_t so = get_scrolloff_value(wp);
|
||||
while (loff.lnum > 1) {
|
||||
// Stop when scrolled nothing or at least "min_scroll", found "extra"
|
||||
// context for 'scrolloff' and counted all lines below the window.
|
||||
@@ -2275,8 +2276,8 @@ void cursor_correct(win_T *wp)
|
||||
{
|
||||
// How many lines we would like to have above/below the cursor depends on
|
||||
// whether the first/last line of the file is on screen.
|
||||
int above_wanted = get_scrolloff_value(wp);
|
||||
int below_wanted = get_scrolloff_value(wp);
|
||||
int64_t above_wanted = get_scrolloff_value(wp);
|
||||
int64_t below_wanted = get_scrolloff_value(wp);
|
||||
if (mouse_dragging > 0) {
|
||||
above_wanted = mouse_dragging - 1;
|
||||
below_wanted = mouse_dragging - 1;
|
||||
|
||||
@@ -2769,7 +2769,7 @@ static void nv_zet(cmdarg_T *cap)
|
||||
int old_fdl = (int)curwin->w_p_fdl;
|
||||
int old_fen = curwin->w_p_fen;
|
||||
|
||||
int siso = get_sidescrolloff_value(curwin);
|
||||
int64_t siso = get_sidescrolloff_value(curwin);
|
||||
|
||||
if (ascii_isdigit(nchar) && !nv_z_get_count(cap, &nchar)) {
|
||||
return;
|
||||
@@ -2890,7 +2890,7 @@ static void nv_zet(cmdarg_T *cap)
|
||||
getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL, 0);
|
||||
}
|
||||
if (col > siso) {
|
||||
col -= siso;
|
||||
col -= (int)siso;
|
||||
} else {
|
||||
col = 0;
|
||||
}
|
||||
@@ -2913,7 +2913,8 @@ static void nv_zet(cmdarg_T *cap)
|
||||
if (col + siso < n) {
|
||||
col = 0;
|
||||
} else {
|
||||
col = col + siso - n + 1;
|
||||
// TODO(zeertzjq): check for overflow
|
||||
col = (int)(col + siso - n + 1);
|
||||
}
|
||||
if (curwin->w_leftcol != col) {
|
||||
curwin->w_leftcol = col;
|
||||
|
||||
@@ -6550,21 +6550,21 @@ dict_T *get_winbuf_options(const int bufopt)
|
||||
|
||||
/// Return the effective 'scrolloff' value for the current window, using the
|
||||
/// global value when appropriate.
|
||||
int get_scrolloff_value(win_T *wp)
|
||||
int64_t get_scrolloff_value(win_T *wp)
|
||||
{
|
||||
// Disallow scrolloff in terminal-mode. #11915
|
||||
// Still allow 'scrolloff' for non-terminal buffers. #34447
|
||||
if ((State & MODE_TERMINAL) && wp->w_buffer->terminal) {
|
||||
return 0;
|
||||
}
|
||||
return (int)(wp->w_p_so < 0 ? p_so : wp->w_p_so);
|
||||
return wp->w_p_so < 0 ? p_so : wp->w_p_so;
|
||||
}
|
||||
|
||||
/// Return the effective 'sidescrolloff' value for the current window, using the
|
||||
/// global value when appropriate.
|
||||
int get_sidescrolloff_value(win_T *wp)
|
||||
int64_t get_sidescrolloff_value(win_T *wp)
|
||||
{
|
||||
return (int)(wp->w_p_siso < 0 ? p_siso : wp->w_p_siso);
|
||||
return wp->w_p_siso < 0 ? p_siso : wp->w_p_siso;
|
||||
}
|
||||
|
||||
Dict get_vimoption(String name, int opt_flags, buf_T *buf, win_T *win, Arena *arena, Error *err)
|
||||
|
||||
@@ -6868,7 +6868,7 @@ static void win_fix_cursor(bool normal)
|
||||
|
||||
wp->w_do_win_fix_cursor = false;
|
||||
// Determine valid cursor range.
|
||||
int so = MIN(wp->w_view_height / 2, get_scrolloff_value(wp));
|
||||
int so = (int)MIN(wp->w_view_height / 2, get_scrolloff_value(wp));
|
||||
linenr_T lnum = wp->w_cursor.lnum;
|
||||
|
||||
wp->w_cursor.lnum = wp->w_topline;
|
||||
|
||||
Reference in New Issue
Block a user