mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #11756 from bfredl/crashfix
custom statusline crash containing unprintable unicode
This commit is contained in:
commit
9a9a4d38a8
@ -3311,7 +3311,7 @@ void maketitle(void)
|
|||||||
buf_p += MIN(size, SPACE_FOR_FNAME);
|
buf_p += MIN(size, SPACE_FOR_FNAME);
|
||||||
} else {
|
} else {
|
||||||
buf_p += transstr_buf((const char *)path_tail(curbuf->b_fname),
|
buf_p += transstr_buf((const char *)path_tail(curbuf->b_fname),
|
||||||
buf_p, SPACE_FOR_FNAME + 1, true);
|
-1, buf_p, SPACE_FOR_FNAME + 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (bufIsChanged(curbuf)
|
switch (bufIsChanged(curbuf)
|
||||||
|
@ -354,14 +354,15 @@ size_t transstr_len(const char *const s, bool untab)
|
|||||||
/// @param[in] untab remove tab characters
|
/// @param[in] untab remove tab characters
|
||||||
///
|
///
|
||||||
/// @return length of the resulting string, without the NUL byte.
|
/// @return length of the resulting string, without the NUL byte.
|
||||||
size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool untab)
|
size_t transstr_buf(const char *const s, const ssize_t slen, char *const buf, const size_t buflen,
|
||||||
|
bool untab)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
const char *p = s;
|
const char *p = s;
|
||||||
char *buf_p = buf;
|
char *buf_p = buf;
|
||||||
char *const buf_e = buf_p + len - 1;
|
char *const buf_e = buf_p + buflen - 1;
|
||||||
|
|
||||||
while (*p != NUL && buf_p < buf_e) {
|
while ((slen < 0 || (p - s) < slen) && *p != NUL && buf_p < buf_e) {
|
||||||
const size_t l = (size_t)utfc_ptr2len(p);
|
const size_t l = (size_t)utfc_ptr2len(p);
|
||||||
if (l > 1) {
|
if (l > 1) {
|
||||||
if (buf_p + l > buf_e) {
|
if (buf_p + l > buf_e) {
|
||||||
@ -416,7 +417,7 @@ char *transstr(const char *const s, bool untab)
|
|||||||
// multi-byte characters.
|
// multi-byte characters.
|
||||||
const size_t len = transstr_len(s, untab) + 1;
|
const size_t len = transstr_len(s, untab) + 1;
|
||||||
char *const buf = xmalloc(len);
|
char *const buf = xmalloc(len);
|
||||||
transstr_buf(s, buf, len, untab);
|
transstr_buf(s, -1, buf, len, untab);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +432,7 @@ size_t kv_transstr(StringBuilder *str, const char *const s, bool untab)
|
|||||||
// multi-byte characters.
|
// multi-byte characters.
|
||||||
const size_t len = transstr_len(s, untab);
|
const size_t len = transstr_len(s, untab);
|
||||||
kv_ensure_space(*str, len + 1);
|
kv_ensure_space(*str, len + 1);
|
||||||
transstr_buf(s, str->items + str->size, len + 1, untab);
|
transstr_buf(s, -1, str->items + str->size, len + 1, untab);
|
||||||
str->size += len; // do not include NUL byte
|
str->size += len; // do not include NUL byte
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -158,9 +158,9 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp)
|
|||||||
/// attributes 'attr', and update chars[] and attrs[].
|
/// attributes 'attr', and update chars[] and attrs[].
|
||||||
/// Note: only outputs within one row, message is truncated at grid boundary!
|
/// Note: only outputs within one row, message is truncated at grid boundary!
|
||||||
/// Note: if grid, row and/or col is invalid, nothing is done.
|
/// Note: if grid, row and/or col is invalid, nothing is done.
|
||||||
void grid_puts(ScreenGrid *grid, char *text, int row, int col, int attr)
|
int grid_puts(ScreenGrid *grid, char *text, int row, int col, int attr)
|
||||||
{
|
{
|
||||||
grid_puts_len(grid, text, -1, row, col, attr);
|
return grid_puts_len(grid, text, -1, row, col, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ScreenGrid *put_dirty_grid = NULL;
|
static ScreenGrid *put_dirty_grid = NULL;
|
||||||
@ -197,7 +197,7 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr)
|
|||||||
|
|
||||||
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
|
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
|
||||||
/// a NUL.
|
/// a NUL.
|
||||||
void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int attr)
|
int grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int attr)
|
||||||
{
|
{
|
||||||
size_t off;
|
size_t off;
|
||||||
char *ptr = text;
|
char *ptr = text;
|
||||||
@ -218,7 +218,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col,
|
|||||||
if (grid->chars == NULL
|
if (grid->chars == NULL
|
||||||
|| row >= grid->rows || row < 0
|
|| row >= grid->rows || row < 0
|
||||||
|| col >= grid->cols || col < 0) {
|
|| col >= grid->cols || col < 0) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (put_dirty_row == -1) {
|
if (put_dirty_row == -1) {
|
||||||
@ -230,6 +230,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
off = grid->line_offset[row] + (size_t)col;
|
off = grid->line_offset[row] + (size_t)col;
|
||||||
|
int start_col = col;
|
||||||
|
|
||||||
// When drawing over the right half of a double-wide char clear out the
|
// When drawing over the right half of a double-wide char clear out the
|
||||||
// left half. Only needed in a terminal.
|
// left half. Only needed in a terminal.
|
||||||
@ -252,6 +253,12 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col,
|
|||||||
? utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr))
|
? utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr))
|
||||||
: utfc_ptr2char(ptr, u8cc);
|
: utfc_ptr2char(ptr, u8cc);
|
||||||
int mbyte_cells = utf_char2cells(u8c);
|
int mbyte_cells = utf_char2cells(u8c);
|
||||||
|
if (mbyte_cells > 2) {
|
||||||
|
mbyte_cells = 1;
|
||||||
|
u8c = 0xFFFD;
|
||||||
|
u8cc[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) {
|
if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) {
|
||||||
// Do Arabic shaping.
|
// Do Arabic shaping.
|
||||||
if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) {
|
if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) {
|
||||||
@ -336,6 +343,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col,
|
|||||||
if (do_flush) {
|
if (do_flush) {
|
||||||
grid_puts_line_flush(true);
|
grid_puts_line_flush(true);
|
||||||
}
|
}
|
||||||
|
return col - start_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// End a group of grid_puts_len calls and send the screen buffer to the UI
|
/// End a group of grid_puts_len calls and send the screen buffer to the UI
|
||||||
|
@ -152,8 +152,8 @@ void win_redr_status(win_T *wp)
|
|||||||
|
|
||||||
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
|
row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp);
|
||||||
col = is_stl_global ? 0 : wp->w_wincol;
|
col = is_stl_global ? 0 : wp->w_wincol;
|
||||||
grid_puts(&default_grid, p, row, col, attr);
|
int width = grid_puts(&default_grid, p, row, col, attr);
|
||||||
grid_fill(&default_grid, row, row + 1, len + col,
|
grid_fill(&default_grid, row, row + 1, width + col,
|
||||||
this_ru_col + col, fillchar, fillchar, attr);
|
this_ru_col + col, fillchar, fillchar, attr);
|
||||||
|
|
||||||
if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL)
|
if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL)
|
||||||
@ -266,6 +266,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
int n;
|
int n;
|
||||||
int fillchar;
|
int fillchar;
|
||||||
char buf[MAXPATHL];
|
char buf[MAXPATHL];
|
||||||
|
char transbuf[MAXPATHL];
|
||||||
char *stl;
|
char *stl;
|
||||||
char *opt_name;
|
char *opt_name;
|
||||||
int opt_scope = 0;
|
int opt_scope = 0;
|
||||||
@ -370,34 +371,25 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
// Make a copy, because the statusline may include a function call that
|
// Make a copy, because the statusline may include a function call that
|
||||||
// might change the option value and free the memory.
|
// might change the option value and free the memory.
|
||||||
stl = xstrdup(stl);
|
stl = xstrdup(stl);
|
||||||
int width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope,
|
build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope,
|
||||||
fillchar, maxwidth, &hltab, &tabtab, NULL);
|
fillchar, maxwidth, &hltab, &tabtab, NULL);
|
||||||
|
|
||||||
xfree(stl);
|
xfree(stl);
|
||||||
ewp->w_p_crb = p_crb_save;
|
ewp->w_p_crb = p_crb_save;
|
||||||
|
|
||||||
// Make all characters printable.
|
int len = (int)strlen(buf);
|
||||||
char *p = transstr(buf, true);
|
int start_col = col;
|
||||||
int len = (int)xstrlcpy(buf, p, sizeof(buf));
|
|
||||||
len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1;
|
|
||||||
xfree(p);
|
|
||||||
|
|
||||||
// fill up with "fillchar"
|
|
||||||
while (width < maxwidth && len < (int)sizeof(buf) - 1) {
|
|
||||||
len += utf_char2bytes(fillchar, buf + len);
|
|
||||||
width++;
|
|
||||||
}
|
|
||||||
buf[len] = NUL;
|
|
||||||
|
|
||||||
// Draw each snippet with the specified highlighting.
|
// Draw each snippet with the specified highlighting.
|
||||||
grid_puts_line_start(grid, row);
|
grid_puts_line_start(grid, row);
|
||||||
|
|
||||||
int curattr = attr;
|
int curattr = attr;
|
||||||
p = buf;
|
char *p = buf;
|
||||||
for (n = 0; hltab[n].start != NULL; n++) {
|
for (n = 0; hltab[n].start != NULL; n++) {
|
||||||
int textlen = (int)(hltab[n].start - p);
|
int textlen = (int)(hltab[n].start - p);
|
||||||
grid_puts_len(grid, p, textlen, row, col, curattr);
|
// Make all characters printable.
|
||||||
col += vim_strnsize(p, textlen);
|
size_t tsize = transstr_buf(p, textlen, transbuf, sizeof transbuf, true);
|
||||||
|
col += grid_puts_len(grid, transbuf, (int)tsize, row, col, curattr);
|
||||||
p = hltab[n].start;
|
p = hltab[n].start;
|
||||||
|
|
||||||
if (hltab[n].userhl == 0) {
|
if (hltab[n].userhl == 0) {
|
||||||
@ -411,7 +403,12 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure to use an empty string instead of p, if p is beyond buf + len.
|
// Make sure to use an empty string instead of p, if p is beyond buf + len.
|
||||||
grid_puts(grid, p >= buf + len ? "" : p, row, col, curattr);
|
size_t tsize = transstr_buf(p >= buf + len ? "" : p, -1, transbuf, sizeof transbuf, true);
|
||||||
|
col += grid_puts_len(grid, transbuf, (int)tsize, row, col, curattr);
|
||||||
|
int maxcol = start_col + maxwidth;
|
||||||
|
|
||||||
|
// fill up with "fillchar"
|
||||||
|
grid_fill(grid, row, row + 1, col, maxcol, fillchar, fillchar, curattr);
|
||||||
|
|
||||||
grid_puts_line_flush(false);
|
grid_puts_line_flush(false);
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ describe('multibyte rendering: statusline', function()
|
|||||||
screen:set_default_attr_ids({
|
screen:set_default_attr_ids({
|
||||||
[1] = {bold = true, foreground = Screen.colors.Blue1},
|
[1] = {bold = true, foreground = Screen.colors.Blue1},
|
||||||
[2] = {bold = true, reverse = true},
|
[2] = {bold = true, reverse = true},
|
||||||
|
[3] = {background = Screen.colors.Red, foreground = Screen.colors.Gray100};
|
||||||
})
|
})
|
||||||
screen:attach()
|
screen:attach()
|
||||||
command('set laststatus=2')
|
command('set laststatus=2')
|
||||||
@ -220,4 +221,27 @@ describe('multibyte rendering: statusline', function()
|
|||||||
|
|
|
|
||||||
]]}
|
]]}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('unprintable chars in filename with default stl', function()
|
||||||
|
command("file 🧑💻")
|
||||||
|
-- TODO: this is wrong but avoids a crash
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{2:🧑<EFBFBD>💻 }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('unprintable chars in filename with custom stl', function()
|
||||||
|
command('set statusline=xx%#ErrorMsg#%f%##yy')
|
||||||
|
command("file 🧑💻")
|
||||||
|
-- TODO: this is also wrong but also avoids a crash
|
||||||
|
screen:expect{grid=[[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{2:xx}{3:🧑<200d>💻}{2:yy }|
|
||||||
|
|
|
||||||
|
]]}
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user