mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.1.0413: smoothscroll may cause infinite loop (#28763)
Problem: smoothscroll may cause infinite loop, with
very narrow windows
(Jaehwang Jung, after v9.1.0280)
Solution: Check for width1 being negative, verify
that win_linetabsize does not overflow
fixes: vim/vim#14750
closes: vim/vim#14772
eff20eb35d
Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
cdd87222c8
commit
acaac07b64
@ -1219,7 +1219,7 @@ static void cursor_correct_sms(win_T *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not enough screen lines in topline: ignore 'scrolloff'.
|
// Not enough screen lines in topline: ignore 'scrolloff'.
|
||||||
while (so_cols > size && so_cols - width2 >= width1) {
|
while (so_cols > size && so_cols - width2 >= width1 && width1 > 0) {
|
||||||
so_cols -= width2;
|
so_cols -= width2;
|
||||||
}
|
}
|
||||||
if (so_cols >= width1 && so_cols > size) {
|
if (so_cols >= width1 && so_cols > size) {
|
||||||
|
@ -57,7 +57,7 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col)
|
|||||||
|
|
||||||
/// Like linetabsize_str(), but "s" starts at virtual column "startvcol".
|
/// Like linetabsize_str(), but "s" starts at virtual column "startvcol".
|
||||||
///
|
///
|
||||||
/// @param startcol
|
/// @param startvcol
|
||||||
/// @param s
|
/// @param s
|
||||||
///
|
///
|
||||||
/// @return Number of cells the string will take on the screen.
|
/// @return Number of cells the string will take on the screen.
|
||||||
@ -76,7 +76,7 @@ int linetabsize_col(int startvcol, char *s)
|
|||||||
/// screen, taking into account the size of a tab and inline virtual text.
|
/// screen, taking into account the size of a tab and inline virtual text.
|
||||||
int linetabsize(win_T *wp, linenr_T lnum)
|
int linetabsize(win_T *wp, linenr_T lnum)
|
||||||
{
|
{
|
||||||
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), (colnr_T)MAXCOL);
|
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), MAXCOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
|
static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
|
||||||
@ -421,48 +421,63 @@ static bool in_win_border(win_T *wp, colnr_T vcol)
|
|||||||
|
|
||||||
/// Calculate virtual column until the given "len".
|
/// Calculate virtual column until the given "len".
|
||||||
///
|
///
|
||||||
/// @param arg Argument to charsize functions.
|
/// @param csarg Argument to charsize functions.
|
||||||
/// @param vcol Starting virtual column.
|
/// @param vcol_arg Starting virtual column.
|
||||||
/// @param len First byte of the end character, or MAXCOL.
|
/// @param len First byte of the end character, or MAXCOL.
|
||||||
///
|
///
|
||||||
/// @return virtual column before the character at "len",
|
/// @return virtual column before the character at "len",
|
||||||
/// or full size of the line if "len" is MAXCOL.
|
/// or full size of the line if "len" is MAXCOL.
|
||||||
int linesize_regular(CharsizeArg *const csarg, int vcol, colnr_T const len)
|
int linesize_regular(CharsizeArg *const csarg, int vcol_arg, colnr_T const len)
|
||||||
{
|
{
|
||||||
char *const line = csarg->line;
|
char *const line = csarg->line;
|
||||||
|
int64_t vcol = vcol_arg;
|
||||||
|
|
||||||
StrCharInfo ci = utf_ptr2StrCharInfo(line);
|
StrCharInfo ci = utf_ptr2StrCharInfo(line);
|
||||||
while (ci.ptr - line < len && *ci.ptr != NUL) {
|
while (ci.ptr - line < len && *ci.ptr != NUL) {
|
||||||
vcol += charsize_regular(csarg, ci.ptr, vcol, ci.chr.value).width;
|
vcol += charsize_regular(csarg, ci.ptr, vcol_arg, ci.chr.value).width;
|
||||||
ci = utfc_next(ci);
|
ci = utfc_next(ci);
|
||||||
|
if (vcol > MAXCOL) {
|
||||||
|
vcol_arg = MAXCOL;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
vcol_arg = (int)vcol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for inline virtual text after the end of the line.
|
// Check for inline virtual text after the end of the line.
|
||||||
if (len == MAXCOL && csarg->virt_row >= 0) {
|
if (len == MAXCOL && csarg->virt_row >= 0 && *ci.ptr == NUL) {
|
||||||
(void)charsize_regular(csarg, ci.ptr, vcol, ci.chr.value);
|
(void)charsize_regular(csarg, ci.ptr, vcol_arg, ci.chr.value);
|
||||||
vcol += csarg->cur_text_width_left + csarg->cur_text_width_right;
|
vcol += csarg->cur_text_width_left + csarg->cur_text_width_right;
|
||||||
|
vcol_arg = vcol > MAXCOL ? MAXCOL : (int)vcol;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vcol;
|
return vcol_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like linesize_regular(), but can be used when CStype is kCharsizeFast.
|
/// Like linesize_regular(), but can be used when CSType is kCharsizeFast.
|
||||||
///
|
///
|
||||||
/// @see linesize_regular
|
/// @see linesize_regular
|
||||||
int linesize_fast(CharsizeArg const *const csarg, int vcol, colnr_T const len)
|
int linesize_fast(CharsizeArg const *const csarg, int vcol_arg, colnr_T const len)
|
||||||
{
|
{
|
||||||
win_T *const wp = csarg->win;
|
win_T *const wp = csarg->win;
|
||||||
bool const use_tabstop = csarg->use_tabstop;
|
bool const use_tabstop = csarg->use_tabstop;
|
||||||
|
|
||||||
char *const line = csarg->line;
|
char *const line = csarg->line;
|
||||||
|
int64_t vcol = vcol_arg;
|
||||||
|
|
||||||
StrCharInfo ci = utf_ptr2StrCharInfo(line);
|
StrCharInfo ci = utf_ptr2StrCharInfo(line);
|
||||||
while (ci.ptr - line < len && *ci.ptr != NUL) {
|
while (ci.ptr - line < len && *ci.ptr != NUL) {
|
||||||
vcol += charsize_fast_impl(wp, use_tabstop, vcol, ci.chr.value).width;
|
vcol += charsize_fast_impl(wp, use_tabstop, vcol_arg, ci.chr.value).width;
|
||||||
ci = utfc_next(ci);
|
ci = utfc_next(ci);
|
||||||
|
if (vcol > MAXCOL) {
|
||||||
|
vcol_arg = MAXCOL;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
vcol_arg = (int)vcol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vcol;
|
return vcol_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get how many virtual columns inline virtual text should offset the cursor.
|
/// Get how many virtual columns inline virtual text should offset the cursor.
|
||||||
@ -572,7 +587,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
|
|||||||
///
|
///
|
||||||
/// @param posp
|
/// @param posp
|
||||||
///
|
///
|
||||||
/// @retujrn The virtual cursor column.
|
/// @return The virtual cursor column.
|
||||||
colnr_T getvcol_nolist(pos_T *posp)
|
colnr_T getvcol_nolist(pos_T *posp)
|
||||||
{
|
{
|
||||||
int list_save = curwin->w_p_list;
|
int list_save = curwin->w_p_list;
|
||||||
|
@ -4278,4 +4278,14 @@ func Test_halfpage_longline()
|
|||||||
call assert_equal(2, line('.'))
|
call assert_equal(2, line('.'))
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for Ctrl-E with long line and very narrow window,
|
||||||
|
" used to cause an inifite loop
|
||||||
|
func Test_scroll_longline_no_loop()
|
||||||
|
4vnew
|
||||||
|
setl smoothscroll number showbreak=> scrolloff=2
|
||||||
|
call setline(1, repeat(['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'], 3))
|
||||||
|
exe "normal! \<C-E>"
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
|
" vim: shiftwidth=2 sts=2 expandtab nofoldenable
|
||||||
|
Loading…
Reference in New Issue
Block a user