From: John Marriott Date: Thu, 26 Feb 2026 21:20:59 +0000 (+0000) Subject: patch 9.2.0068: Inefficient use of list_append_string() X-Git-Tag: v9.2.0068^0 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=455d62e38a75572bccc43e42d20b5db3c4b22ec3;p=thirdparty%2Fvim.git patch 9.2.0068: Inefficient use of list_append_string() Problem: Inefficient use of list_append_string() Solution: Pass string length to list_append_string() where it is known (John Marriott). closes: #19491 Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- diff --git a/src/clipboard.c b/src/clipboard.c index 9223e8101b..e4650c1b7a 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -3838,7 +3838,8 @@ clip_provider_copy(char_u *reg, char_u *provider) } for (int i = 0; i < y_ptr->y_size; i++) - if (list_append_string(list, y_ptr->y_array[i].string, -1) == FAIL) + if (list_append_string(list, y_ptr->y_array[i].string, + (int)y_ptr->y_array[i].length) == FAIL) { free_callback(&callback); list_unref(list); diff --git a/src/evalbuffer.c b/src/evalbuffer.c index 03d946a0f7..29d0f92f8a 100644 --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -785,8 +785,6 @@ get_buffer_lines( int retlist, typval_T *rettv) { - char_u *p; - if (retlist) { if (rettv_list_alloc(rettv) == FAIL) @@ -804,10 +802,11 @@ get_buffer_lines( if (!retlist) { if (start >= 1 && start <= buf->b_ml.ml_line_count) - p = ml_get_buf(buf, start, FALSE); + rettv->vval.v_string = + vim_strnsave(ml_get_buf(buf, start, FALSE), + ml_get_buf_len(buf, start)); else - p = (char_u *)""; - rettv->vval.v_string = vim_strsave(p); + rettv->vval.v_string = vim_strnsave((char_u *)"", 0); } else { @@ -819,9 +818,13 @@ get_buffer_lines( if (end > buf->b_ml.ml_line_count) end = buf->b_ml.ml_line_count; while (start <= end) + { if (list_append_string(rettv->vval.v_list, - ml_get_buf(buf, start++, FALSE), -1) == FAIL) + ml_get_buf(buf, start, FALSE), + (int)ml_get_buf_len(buf, start)) == FAIL) break; + ++start; + } } } diff --git a/src/evalfunc.c b/src/evalfunc.c index b4dd971f46..139d940cc2 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -6023,24 +6023,25 @@ f_getpos(typval_T *argvars, typval_T *rettv) /* * Convert from block_def to string */ - static char_u * -block_def2str(struct block_def *bd) + static int +block_def2str(struct block_def *bd, string_T *ret) { - char_u *p, *ret; - size_t size = bd->startspaces + bd->endspaces + bd->textlen; - - ret = alloc(size + 1); - if (ret != NULL) + ret->string = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1); + if (ret->string == NULL) { - p = ret; - vim_memset(p, ' ', bd->startspaces); - p += bd->startspaces; - mch_memmove(p, bd->textstart, bd->textlen); - p += bd->textlen; - vim_memset(p, ' ', bd->endspaces); - *(p + bd->endspaces) = NUL; + ret->length = 0; + return FAIL; } - return ret; + + vim_memset(ret->string, ' ', bd->startspaces); + ret->length = bd->startspaces; + mch_memmove(ret->string + ret->length, bd->textstart, bd->textlen); + ret->length += bd->textlen; + vim_memset(ret->string + ret->length, ' ', bd->endspaces); + ret->length += bd->endspaces; + ret->string[ret->length] = NUL; + + return OK; } static int @@ -6221,7 +6222,7 @@ f_getregion(typval_T *argvars, typval_T *rettv) buf_T *save_curbuf; int save_virtual; - char_u *akt = NULL; + string_T akt = {NULL, 0}; linenr_T lnum; save_curbuf = curbuf; @@ -6233,31 +6234,47 @@ f_getregion(typval_T *argvars, typval_T *rettv) for (lnum = p1.lnum; lnum <= p2.lnum; lnum++) { - int ret = 0; - struct block_def bd; + int ret = OK; - if (region_type == MLINE) - akt = vim_strsave(ml_get(lnum)); - else if (region_type == MBLOCK) + if (region_type == MBLOCK) { + struct block_def bd; + block_prep(&oa, &bd, lnum, FALSE); - akt = block_def2str(&bd); + block_def2str(&bd, &akt); + } + else if (region_type == MLINE + || (p1.lnum < lnum && lnum < p2.lnum)) + { + string_T s; + + s.string = ml_get(lnum); + s.length = ml_get_len(lnum); + akt.string = vim_strnsave(s.string, s.length); + if (akt.string == NULL) + akt.length = 0; + else + akt.length = s.length; } - else if (p1.lnum < lnum && lnum < p2.lnum) - akt = vim_strsave(ml_get(lnum)); else { + struct block_def bd; + charwise_block_prep(p1, p2, &bd, lnum, inclusive); - akt = block_def2str(&bd); + block_def2str(&bd, &akt); } - if (akt) + if (akt.string == NULL) { - ret = list_append_string(rettv->vval.v_list, akt, -1); - vim_free(akt); + clear_tv(rettv); + (void)rettv_list_alloc(rettv); + break; } - if (akt == NULL || ret == FAIL) + ret = list_append_string(rettv->vval.v_list, akt.string, (int)akt.length); + vim_free(akt.string); + + if (ret == FAIL) { clear_tv(rettv); (void)rettv_list_alloc(rettv); @@ -11954,12 +11971,28 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv) #endif list_append_string(rettv->vval.v_list, word, len); - list_append_string(rettv->vval.v_list, (char_u *)( - attr == HLF_SPB ? "bad" : - attr == HLF_SPR ? "rare" : - attr == HLF_SPL ? "local" : - attr == HLF_SPC ? "caps" : - ""), -1); + switch (attr) + { + case HLF_SPB: + list_append_string(rettv->vval.v_list, (char_u *)"bad", STRLEN_LITERAL("bad")); + break; + + case HLF_SPR: + list_append_string(rettv->vval.v_list, (char_u *)"rare", STRLEN_LITERAL("rare")); + break; + + case HLF_SPL: + list_append_string(rettv->vval.v_list, (char_u *)"local", STRLEN_LITERAL("local")); + break; + + case HLF_SPC: + list_append_string(rettv->vval.v_list, (char_u *)"caps", STRLEN_LITERAL("caps")); + break; + + default: + list_append_string(rettv->vval.v_list, (char_u *)"", 0); + break; + } } /* diff --git a/src/evalwindow.c b/src/evalwindow.c index a08cbf717d..53116c7a1d 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -293,14 +293,16 @@ get_framelayout(frame_T *fr, list_T *l, int outer) { if (fr->fr_win != NULL) { - list_append_string(fr_list, (char_u *)"leaf", -1); + list_append_string(fr_list, (char_u *)"leaf", STRLEN_LITERAL("leaf")); list_append_number(fr_list, fr->fr_win->w_id); } } else { - list_append_string(fr_list, - fr->fr_layout == FR_ROW ? (char_u *)"row" : (char_u *)"col", -1); + if (fr->fr_layout == FR_ROW) + list_append_string(fr_list, (char_u *)"row", STRLEN_LITERAL("row")); + else + list_append_string(fr_list, (char_u *)"col", STRLEN_LITERAL("col")); win_list = list_alloc(); if (win_list == NULL) diff --git a/src/register.c b/src/register.c index 1f1739160f..1fdebce95e 100644 --- a/src/register.c +++ b/src/register.c @@ -1097,7 +1097,7 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg) // yanked text contents for (n = 0; n < reg->y_size; n++) - list_append_string(list, reg->y_array[n].string, -1); + list_append_string(list, reg->y_array[n].string, (int)reg->y_array[n].length); list->lv_lock = VAR_FIXED; (void)dict_add_list(v_event, "regcontents", list); @@ -2793,17 +2793,17 @@ get_reg_contents(int regname, int flags) if (flags & GREG_LIST) { list_T *list = list_alloc(); - int error = FALSE; if (list == NULL) return NULL; for (i = 0; i < y_current->y_size; ++i) - if (list_append_string(list, y_current->y_array[i].string, -1) == FAIL) - error = TRUE; - if (error) { - list_free(list); - return NULL; + if (list_append_string(list, y_current->y_array[i].string, + (int)y_current->y_array[i].length) == FAIL) + { + list_free(list); + return NULL; + } } return (char_u *)list; } diff --git a/src/strings.c b/src/strings.c index 8b44a2d2be..5870850991 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1197,22 +1197,31 @@ f_charidx(typval_T *argvars, typval_T *rettv) /* * Convert the string "str", from encoding "from" to encoding "to". */ - static char_u * -convert_string(char_u *str, char_u *from, char_u *to) + static int +convert_string(string_T *str, char_u *from, char_u *to, string_T *ret) { vimconv_T vimconv; vimconv.vc_type = CONV_NONE; if (convert_setup(&vimconv, from, to) == FAIL) - return NULL; + return FAIL; vimconv.vc_fail = TRUE; if (vimconv.vc_type == CONV_NONE) - str = vim_strsave(str); + { + ret->string = vim_strnsave(str->string, str->length); + if (ret->string == NULL) + ret->length = 0; + else + ret->length = str->length; + } else - str = string_convert(&vimconv, str, NULL); + { + ret->length = str->length; + ret->string = string_convert(&vimconv, str->string, (int *)&ret->length); + } convert_setup(&vimconv, NULL, NULL); - return str; + return (ret->string == NULL) ? FAIL : OK; } /* @@ -1238,13 +1247,12 @@ blob_from_string(char_u *str, blob_T *blob) * allocated string is returned and "start_idx" is moved forward by one byte. * On return, "start_idx" points to next byte to process in blob. */ - static char_u * -string_from_blob(blob_T *blob, long *start_idx) + static int +string_from_blob(blob_T *blob, long *start_idx, string_T *ret) { garray_T str_ga; long blen; int idx; - char_u *ret_str = NULL; ga_init2(&str_ga, sizeof(char), 80); @@ -1266,13 +1274,19 @@ string_from_blob(blob_T *blob, long *start_idx) } if (str_ga.ga_data != NULL) - ret_str = vim_strnsave(str_ga.ga_data, str_ga.ga_len); + { + ret->string = vim_strnsave(str_ga.ga_data, str_ga.ga_len); + ret->length = str_ga.ga_len; + } else - ret_str = vim_strsave((char_u *)""); + { + ret->string = vim_strsave((char_u *)""); + ret->length = 0; + } *start_idx = idx; ga_clear(&str_ga); - return ret_str; + return (ret->string == NULL) ? FAIL : OK; } /* @@ -1320,56 +1334,57 @@ normalize_encoding_name(char_u *enc_skipped) */ static void append_converted_string_to_list( - char_u *converted, + string_T *converted, int validate_utf8, list_T *list, char_u *from_encoding) { - if (converted != NULL) + if (converted->string != NULL) { // After conversion, the output is a valid UTF-8 string (NUL-terminated) - int converted_len = (int)STRLEN(converted); - // Split by newlines and add to list - char_u *p = converted; - char_u *end = converted + converted_len; + char_u *p = converted->string; + char_u *end = converted->string + converted->length; while (p < end) { - char_u *line_start = p; + string_T line; + char_u *line_start = p; + while (p < end && *p != NL) p++; // Add this line to the result list - char_u *line = vim_strnsave(line_start, p - line_start); - if (line != NULL) + line.length = (size_t)(p - line_start); + line.string = vim_strnsave(line_start, line.length); + if (line.string != NULL) { - if (validate_utf8 && !utf_valid_string(line, NULL)) + if (validate_utf8 && !utf_valid_string(line.string, NULL)) { - vim_free(line); + vim_free(line.string); semsg(_(e_str_encoding_from_failed), p_enc); - vim_free(converted); + vim_free(converted->string); return; // Stop processing } - if (list_append_string(list, line, -1) == FAIL) + if (list_append_string(list, line.string, (int)line.length) == FAIL) { - vim_free(line); - vim_free(converted); + vim_free(line.string); + vim_free(converted->string); return; // Stop processing on append failure } - vim_free(line); + vim_free(line.string); } else { // Allocation failure: report error and stop processing emsg(_(e_out_of_memory)); - vim_free(converted); + vim_free(converted->string); return; } if (*p == NL) p++; } - vim_free(converted); + vim_free(converted->string); } else { @@ -1378,17 +1393,17 @@ append_converted_string_to_list( } static int -append_validated_line_to_list(char_u *line, int validate_utf8, list_T *list) +append_validated_line_to_list(string_T *line, int validate_utf8, list_T *list) { - if (validate_utf8 && !utf_valid_string(line, NULL)) + if (validate_utf8 && !utf_valid_string(line->string, NULL)) { semsg(_(e_str_encoding_from_failed), p_enc); - vim_free(line); + vim_free(line->string); return FAIL; } - int ret = list_append_string(list, line, -1); - vim_free(line); + int ret = list_append_string(list, line->string, (int)line->length); + vim_free(line->string); return ret; } @@ -1477,12 +1492,16 @@ f_blob2str(typval_T *argvars, typval_T *rettv) goto done; } vimconv.vc_fail = TRUE; + // Use string_convert_ext with explicit input length - int inlen = blen; - char_u *converted = string_convert_ext(&vimconv, (char_u *)blob_ga.ga_data, &inlen, NULL); + string_T converted; + + converted.length = blen; + converted.string = + string_convert_ext(&vimconv, (char_u *)blob_ga.ga_data, (int *)&converted.length, NULL); convert_setup(&vimconv, NULL, NULL); ga_clear(&blob_ga); - append_converted_string_to_list(converted, validate_utf8, rettv->vval.v_list, from_encoding); + append_converted_string_to_list(&converted, validate_utf8, rettv->vval.v_list, from_encoding); } else { @@ -1490,27 +1509,29 @@ f_blob2str(typval_T *argvars, typval_T *rettv) idx = 0; while (idx < blen) { - char_u *str; + string_T str; - str = string_from_blob(blob, &idx); - if (str == NULL) + if (string_from_blob(blob, &idx, &str) != OK) break; if (from_encoding != NULL) { // from_encoding_raw is guaranteed non-NULL whenever from_encoding != NULL - char_u *converted = convert_string(str, from_encoding_raw, p_enc); - vim_free(str); - str = converted; - } + int res; + string_T converted; - if (str == NULL) - { - semsg(_(e_str_encoding_from_failed), from_encoding); - goto done; + res = convert_string(&str, from_encoding_raw, p_enc, &converted); + vim_free(str.string); + if (res != OK) + { + semsg(_(e_str_encoding_from_failed), from_encoding); + goto done; + } + str.string = converted.string; + str.length = converted.length; } - if (append_validated_line_to_list(str, validate_utf8, rettv->vval.v_list) == FAIL) + if (append_validated_line_to_list(&str, validate_utf8, rettv->vval.v_list) == FAIL) goto done; } } @@ -1564,29 +1585,39 @@ f_str2blob(typval_T *argvars, typval_T *rettv) if (li->li_tv.v_type != VAR_STRING) continue; - char_u *str = li->li_tv.vval.v_string; + string_T str = {li->li_tv.vval.v_string, 0}; - if (str == NULL) - str = (char_u *)""; + if (str.string == NULL) + { + str.string = (char_u *)""; + str.length = 0; + } + else + str.length = STRLEN(str.string); if (to_encoding != NULL) { - str = convert_string(str, p_enc, to_encoding); - if (str == NULL) + int res; + string_T converted; + + res = convert_string(&str, p_enc, to_encoding, &converted); + if (res != OK) { semsg(_(e_str_encoding_to_failed), to_encoding); goto done; } + str.string = converted.string; + str.length = converted.length; } if (li != list->lv_first) // Each list string item is separated by a newline in the blob ga_append(&blob->bv_ga, NL); - blob_from_string(str, blob); + blob_from_string(str.string, blob); if (to_encoding != NULL) - vim_free(str); + vim_free(str.string); } done: diff --git a/src/terminal.c b/src/terminal.c index 8a479f71df..0753c2892a 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -6704,10 +6704,12 @@ f_term_getansicolors(typval_T *argvars, typval_T *rettv) state = vterm_obtain_state(term->tl_vterm); for (index = 0; index < 16; index++) { + size_t hexbuflen; + vterm_state_get_palette_color(state, index, &color); - sprintf((char *)hexbuf, "#%02x%02x%02x", - color.red, color.green, color.blue); - if (list_append_string(list, hexbuf, 7) == FAIL) + hexbuflen = vim_snprintf_safelen((char *)hexbuf, sizeof(hexbuf), + "#%02x%02x%02x", color.red, color.green, color.blue); + if (list_append_string(list, hexbuf, (int)hexbuflen) == FAIL) return; } } diff --git a/src/version.c b/src/version.c index d6194a9801..c93ea19fb0 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 68, /**/ 67, /**/