From: John Marriott Date: Wed, 8 Jan 2025 19:10:59 +0000 (+0100) Subject: patch 9.1.0997: too many strlen() calls in drawscreen.c X-Git-Tag: v9.1.0997^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a21240b97debea2e087aee6ad1488b5f075d1259;p=thirdparty%2Fvim.git patch 9.1.0997: too many strlen() calls in drawscreen.c Problem: too many strlen() calls in drawscreen.c Solution: refactor drawscreen.c and remove calls to strlen(), make get_keymap_str() (in screen.c) return string length instead of TRUE/FALSE (John Marriott). Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- diff --git a/src/buffer.c b/src/buffer.c index 147d20dc78..a925552199 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3914,7 +3914,7 @@ fileinfo( n); validate_virtcol(); len = STRLEN(buffer); - col_print((char_u *)buffer + len, IOSIZE - len, + (void)col_print((char_u *)buffer + len, IOSIZE - len, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); } @@ -3946,7 +3946,7 @@ fileinfo( vim_free(buffer); } - void + int col_print( char_u *buf, size_t buflen, @@ -3954,9 +3954,9 @@ col_print( int vcol) { if (col == vcol) - vim_snprintf((char *)buf, buflen, "%d", col); - else - vim_snprintf((char *)buf, buflen, "%d-%d", col, vcol); + return vim_snprintf((char *)buf, buflen, "%d", col); + + return vim_snprintf((char *)buf, buflen, "%d-%d", col, vcol); } static char_u *lasttitle = NULL; @@ -4820,7 +4820,7 @@ build_stl_str_hl( case STL_ALTPERCENT: str = buf_tmp; - get_rel_pos(wp, str, TMPLEN); + (void)get_rel_pos(wp, str, TMPLEN); break; case STL_SHOWCMD: @@ -4837,7 +4837,7 @@ build_stl_str_hl( case STL_KEYMAP: fillable = FALSE; - if (get_keymap_str(wp, (char_u *)"<%s>", buf_tmp, TMPLEN)) + if (get_keymap_str(wp, (char_u *)"<%s>", buf_tmp, TMPLEN) > 0) str = buf_tmp; break; case STL_PAGENUM: @@ -5271,7 +5271,7 @@ build_stl_str_hl( * Get relative cursor position in window into "buf[buflen]", in the localized * percentage form like %99, 99%; using "Top", "Bot" or "All" when appropriate. */ - void + int get_rel_pos( win_T *wp, char_u *buf, @@ -5279,9 +5279,10 @@ get_rel_pos( { long above; // number of lines above window long below; // number of lines below window + int len; if (buflen < 3) // need at least 3 chars for writing - return; + return 0; above = wp->w_topline - 1; #ifdef FEAT_DIFF above += diff_check_fill(wp, wp->w_topline) - wp->w_topfill; @@ -5292,28 +5293,27 @@ get_rel_pos( #endif below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1; if (below <= 0) - vim_strncpy(buf, (char_u *)(above == 0 ? _("All") : _("Bot")), - (size_t)(buflen - 1)); + len = vim_snprintf((char *)buf, buflen, "%s", (above == 0) ? _("All") : _("Bot")); else if (above <= 0) - vim_strncpy(buf, (char_u *)_("Top"), (size_t)(buflen - 1)); + len = vim_snprintf((char *)buf, buflen, "%s", _("Top")); else { int perc = (above > 1000000L) - ? (int)(above / ((above + below) / 100L)) - : (int)(above * 100L / (above + below)); + ? (int)(above / ((above + below) / 100L)) + : (int)(above * 100L / (above + below)); - char *p = (char *)buf; - size_t l = buflen; - if (perc < 10) - { - // prepend one space - buf[0] = ' '; - ++p; - --l; - } // localized percentage value - vim_snprintf(p, l, _("%d%%"), perc); + len = vim_snprintf((char *)buf, buflen, _("%s%d%%"), (perc < 10) ? " " : "", perc); } + if (len < 0) + { + buf[0] = NUL; + len = 0; + } + else if (len > buflen - 1) + len = buflen - 1; + + return len; } /* diff --git a/src/drawscreen.c b/src/drawscreen.c index 778cda4d4f..36034cc9df 100644 --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -425,11 +425,8 @@ statusline_row(win_T *wp) win_redr_status(win_T *wp, int ignore_pum UNUSED) { int row; - char_u *p; - int len; int fillchar; int attr; - int this_ru_col; static int busy = FALSE; // It's possible to get here recursively when 'statusline' (indirectly) @@ -463,11 +460,17 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED) #endif else { + char_u *p; + int plen; + int NameBufflen; + int this_ru_col; + int n; // scratch value + fillchar = fillchar_status(&attr, wp); get_trans_bufname(wp->w_buffer); p = NameBuff; - len = (int)STRLEN(p); + plen = (int)STRLEN(p); if ((bt_help(wp->w_buffer) #ifdef FEAT_QUICKFIX @@ -475,74 +478,61 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED) #endif || bufIsChanged(wp->w_buffer) || wp->w_buffer->b_p_ro) - && len < MAXPATHL - 1) - *(p + len++) = ' '; + && plen < MAXPATHL - 1) + *(p + plen++) = ' '; if (bt_help(wp->w_buffer)) - { - vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Help]")); - len += (int)STRLEN(p + len); - } + plen += vim_snprintf((char *)p + plen, MAXPATHL - plen, "%s", _("[Help]")); #ifdef FEAT_QUICKFIX if (wp->w_p_pvw) - { - vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Preview]")); - len += (int)STRLEN(p + len); - } + plen += vim_snprintf((char *)p + plen, MAXPATHL - plen, "%s", _("[Preview]")); #endif if (bufIsChanged(wp->w_buffer) && !bt_terminal(wp->w_buffer)) - { - vim_snprintf((char *)p + len, MAXPATHL - len, "%s", "[+]"); - len += (int)STRLEN(p + len); - } + plen += vim_snprintf((char *)p + plen, MAXPATHL - plen, "%s", "[+]"); if (wp->w_buffer->b_p_ro) - { - vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[RO]")); - len += (int)STRLEN(p + len); - } + plen += vim_snprintf((char *)p + plen, MAXPATHL - plen, "%s", _("[RO]")); this_ru_col = ru_col - (Columns - wp->w_width); - if (this_ru_col < (wp->w_width + 1) / 2) - this_ru_col = (wp->w_width + 1) / 2; + n = (wp->w_width + 1) / 2; + if (this_ru_col < n) + this_ru_col = n; if (this_ru_col <= 1) { p = (char_u *)"<"; // No room for file name! - len = 1; + plen = 1; } else if (has_mbyte) { - int clen = 0, i; + int i; // Count total number of display cells. - clen = mb_string2cells(p, -1); + plen = mb_string2cells(p, -1); // Find first character that will fit. // Going from start to end is much faster for DBCS. - for (i = 0; p[i] != NUL && clen >= this_ru_col - 1; + for (i = 0; p[i] != NUL && plen >= this_ru_col - 1; i += (*mb_ptr2len)(p + i)) - clen -= (*mb_ptr2cells)(p + i); - len = clen; + plen -= (*mb_ptr2cells)(p + i); if (i > 0) { p = p + i - 1; *p = '<'; - ++len; + ++plen; } - } - else if (len > this_ru_col - 1) + else if (plen > this_ru_col - 1) { - p += len - (this_ru_col - 1); + p += plen - (this_ru_col - 1); *p = '<'; - len = this_ru_col - 1; + plen = this_ru_col - 1; } screen_puts(p, row, wp->w_wincol, attr); - screen_fill(row, row + 1, len + wp->w_wincol, + screen_fill(row, row + 1, plen + wp->w_wincol, this_ru_col + wp->w_wincol, fillchar, fillchar, attr); - if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL) - && (this_ru_col - len) > (int)(STRLEN(NameBuff) + 1)) - screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff) + if ((NameBufflen = get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)) > 0 + && (this_ru_col - plen) > (NameBufflen + 1)) + screen_puts(NameBuff, row, (int)(this_ru_col - NameBufflen - 1 + wp->w_wincol), attr); win_redr_ruler(wp, TRUE, ignore_pum); @@ -550,7 +540,8 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED) // Draw the 'showcmd' information if 'showcmdloc' == "statusline". if (p_sc && *p_sloc == 's') { - int width = MIN(10, this_ru_col - len - 2); + n = this_ru_col - plen - 2; // perform the calculation here so we only do it once + int width = MIN(10, n); if (width > 0) screen_puts_len(showcmd_buf, width, row, @@ -631,19 +622,7 @@ showruler(int always) void win_redr_ruler(win_T *wp, int always, int ignore_pum) { -#define RULER_BUF_LEN 70 - char_u buffer[RULER_BUF_LEN]; - int row; - int fillchar; - int attr; - int empty_line = FALSE; - colnr_T virtcol; - int i; - size_t len; - int o; - int this_ru_col; - int off = 0; - int width; + int empty_line = FALSE; // If 'ruler' off don't do anything if (!p_ru) @@ -661,6 +640,7 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum) if (wp == lastwin && lastwin->w_status_height == 0) if (edit_submode != NULL) return; + // Don't draw the ruler when the popup menu is visible, it may overlap. // Except when the popup menu will be redrawn anyway. if (!ignore_pum && pum_visible()) @@ -698,6 +678,21 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum) #endif || empty_line != wp->w_ru_empty) { + int row; + int fillchar; + int attr; + int off; + int width; + colnr_T virtcol; +#define RULER_BUF_LEN 70 + char_u buffer[RULER_BUF_LEN]; + int bufferlen; + char_u rel_pos[RULER_BUF_LEN]; + int rel_poslen; + int this_ru_col; + int n1; // scratch value + int n2; // scratch value + cursor_off(); if (wp->w_status_height) { @@ -724,16 +719,11 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum) wp->w_p_list = TRUE; } - /* - * Some sprintfs return the length, some return a pointer. - * To avoid portability problems we use strlen() here. - */ - vim_snprintf((char *)buffer, RULER_BUF_LEN, "%ld,", + bufferlen = vim_snprintf((char *)buffer, RULER_BUF_LEN, "%ld,", (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum)); - len = STRLEN(buffer); - col_print(buffer + len, RULER_BUF_LEN - len, + bufferlen += col_print(buffer + bufferlen, RULER_BUF_LEN - bufferlen, empty_line ? 0 : (int)wp->w_cursor.col + 1, (int)virtcol + 1); @@ -742,56 +732,60 @@ win_redr_ruler(win_T *wp, int always, int ignore_pum) * On the last line, don't print in the last column (scrolls the * screen up on some terminals). */ - i = (int)STRLEN(buffer); - get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1); - o = i + vim_strsize(buffer + i + 1); + rel_poslen = get_rel_pos(wp, rel_pos, RULER_BUF_LEN); + n1 = bufferlen + vim_strsize(rel_pos); if (wp->w_status_height == 0) // can't use last char of screen - ++o; + ++n1; + this_ru_col = ru_col - (Columns - width); - if (this_ru_col < 0) - this_ru_col = 0; // Never use more than half the window/screen width, leave the other // half for the filename. - if (this_ru_col < (width + 1) / 2) - this_ru_col = (width + 1) / 2; - if (this_ru_col + o < width) - { - // need at least 3 chars left for get_rel_pos() + NUL - while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) + n2 = (width + 1) / 2; + if (this_ru_col < n2) + this_ru_col = n2; + if (this_ru_col + n1 < width) + { + // need at least space for rel_pos + NUL + while (this_ru_col + n1 < width + && RULER_BUF_LEN > bufferlen + rel_poslen + 1) // +1 for NUL { if (has_mbyte) - i += (*mb_char2bytes)(fillchar, buffer + i); + bufferlen += (*mb_char2bytes)(fillchar, buffer + bufferlen); else - buffer[i++] = fillchar; - ++o; + buffer[bufferlen++] = fillchar; + ++n1; } - get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i); + bufferlen += vim_snprintf((char *)buffer + bufferlen, RULER_BUF_LEN - bufferlen, + "%s", rel_pos); } // Truncate at window boundary. if (has_mbyte) { - o = 0; - for (i = 0; buffer[i] != NUL; i += (*mb_ptr2len)(buffer + i)) + for (n1 = 0, n2 = 0; buffer[n1] != NUL; n1 += (*mb_ptr2len)(buffer + n1)) { - o += (*mb_ptr2cells)(buffer + i); - if (this_ru_col + o > width) + n2 += (*mb_ptr2cells)(buffer + n1); + if (this_ru_col + n2 > width) { - buffer[i] = NUL; + bufferlen = n1; + buffer[bufferlen] = NUL; break; } } } - else if (this_ru_col + (int)STRLEN(buffer) > width) - buffer[width - this_ru_col] = NUL; + else if (this_ru_col + bufferlen > width) + { + bufferlen = width - this_ru_col; + buffer[bufferlen] = NUL; + } screen_puts(buffer, row, this_ru_col + off, attr); - i = redraw_cmdline; + n1 = redraw_cmdline; screen_fill(row, row + 1, - this_ru_col + off + (int)STRLEN(buffer), + this_ru_col + off + bufferlen, (off + width), fillchar, fillchar, attr); // don't redraw the cmdline because of showing the ruler - redraw_cmdline = i; + redraw_cmdline = n1; wp->w_ru_cursor = wp->w_cursor; wp->w_ru_virtcol = wp->w_virtcol; wp->w_ru_empty = empty_line; @@ -948,9 +942,10 @@ text_to_screenline(win_T *wp, char_u *text, int col) else { int len = (int)STRLEN(text); + int n = wp->w_width - col; - if (len > wp->w_width - col) - len = wp->w_width - col; + if (len > n) + len = n; if (len > 0) { #ifdef FEAT_RIGHTLEFT @@ -1217,7 +1212,7 @@ fold_line( } } - sprintf((char *)buf, fmt, w, num); + vim_snprintf((char *)buf, sizeof(buf), fmt, w, num); #ifdef FEAT_RIGHTLEFT if (wp->w_p_rl) // the line number isn't reversed @@ -2048,8 +2043,7 @@ win_update(win_T *wp) { colnr_T t; - pos.col = (int)STRLEN(ml_get_buf(wp->w_buffer, - pos.lnum, FALSE)); + pos.col = (int)ml_get_buf_len(wp->w_buffer, pos.lnum); getvvcol(wp, &pos, NULL, NULL, &t); if (toc < t) toc = t; diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro index dc68ca8fc1..5491940daf 100644 --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -44,12 +44,12 @@ void buflist_altfpos(win_T *win); int otherfile(char_u *ffname); void buf_setino(buf_T *buf); void fileinfo(int fullname, int shorthelp, int dont_truncate); -void col_print(char_u *buf, size_t buflen, int col, int vcol); +int col_print(char_u *buf, size_t buflen, int col, int vcol); void maketitle(void); void resettitle(void); void free_titles(void); int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, char_u *opt_name, int opt_scope, int fillchar, int maxwidth, stl_hlrec_T **hltab, stl_hlrec_T **tabtab); -void get_rel_pos(win_T *wp, char_u *buf, int buflen); +int get_rel_pos(win_T *wp, char_u *buf, int buflen); char_u *fix_fname(char_u *fname); void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname); void ex_buffer_all(exarg_T *eap); diff --git a/src/screen.c b/src/screen.c index 35d300213b..8fb17ae87a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -968,20 +968,21 @@ get_keymap_str( int len) // length of buffer { char_u *p; + int plen; if (wp->w_buffer->b_p_iminsert != B_IMODE_LMAP) - return FALSE; + return 0; #ifdef FEAT_EVAL buf_T *old_curbuf = curbuf; win_T *old_curwin = curwin; + char_u to_evaluate[] = "b:keymap_name"; char_u *s; curbuf = wp->w_buffer; curwin = wp; - STRCPY(buf, "b:keymap_name"); // must be writable ++emsg_skip; - s = p = eval_to_string(buf, FALSE, FALSE); + s = p = eval_to_string(to_evaluate, FALSE, FALSE); --emsg_skip; curbuf = old_curbuf; curwin = old_curwin; @@ -995,12 +996,17 @@ get_keymap_str( #endif p = (char_u *)"lang"; } - if (vim_snprintf((char *)buf, len, (char *)fmt, p) > len - 1) - buf[0] = NUL; + plen = vim_snprintf((char *)buf, len, (char *)fmt, p); #ifdef FEAT_EVAL vim_free(s); #endif - return buf[0] != NUL; + if (plen < 0 || plen > len - 1) + { + buf[0] = NUL; + plen = 0; + } + + return plen; } #if defined(FEAT_STL_OPT) || defined(PROTO) @@ -4133,7 +4139,7 @@ showmode(void) else # endif if (get_keymap_str(curwin, (char_u *)" (%s)", - NameBuff, MAXPATHL)) + NameBuff, MAXPATHL) > 0) msg_puts_attr((char *)NameBuff, attr); } #endif diff --git a/src/version.c b/src/version.c index 38f46927d0..22efc7e6bb 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 997, /**/ 996, /**/