vim-patch:partial:9.2.0068: Inefficient use of list_append_string() (#38083)

Problem:  Inefficient use of list_append_string()
Solution: Pass string length to list_append_string() where it is known
          (John Marriott).

closes: vim/vim#19491

455d62e38a

N/A patches:
vim-patch:9.2.0063: memory leak in type_name_list_or_dict()
vim-patch:9.2.0065: memory leak in invoke_sync_listeners()
vim-patch:9.2.0066: memory leak in build_drop_cmd()
vim-patch:9.2.0067: memory leak in dict_extend_func()

Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
zeertzjq
2026-02-27 07:32:08 +08:00
committed by GitHub
parent 6435c61bd6
commit 18c5f06c9f
5 changed files with 45 additions and 31 deletions

View File

@@ -209,7 +209,7 @@ void set_clipboard(int name, yankreg_T *reg)
list_T *const lines = tv_list_alloc((ptrdiff_t)reg->y_size + (reg->y_type != kMTCharWise));
for (size_t i = 0; i < reg->y_size; i++) {
tv_list_append_string(lines, reg->y_array[i].data, -1);
tv_list_append_string(lines, reg->y_array[i].data, (int)reg->y_array[i].size);
}
char regtype;

View File

@@ -611,12 +611,16 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, bool retl
}
tv_list_alloc_ret(rettv, end - start + 1);
while (start <= end) {
tv_list_append_string(rettv->vval.v_list, ml_get_buf(buf, start++), -1);
tv_list_append_string(rettv->vval.v_list,
ml_get_buf(buf, start), (int)ml_get_buf_len(buf, start));
start++;
}
} else {
rettv->v_type = VAR_STRING;
rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count)
? xstrdup(ml_get_buf(buf, start)) : NULL);
rettv->vval.v_string =
start >= 1 && start <= buf->b_ml.ml_line_count
? xstrnsave(ml_get_buf(buf, start), (size_t)ml_get_buf_len(buf, start))
: NULL;
}
}

View File

@@ -2161,17 +2161,19 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
/// Convert from block_def to string
static char *block_def2str(struct block_def *bd)
static String block_def2str(struct block_def *bd)
{
size_t size = (size_t)bd->startspaces + (size_t)bd->endspaces + (size_t)bd->textlen;
char *ret = xmalloc(size + 1);
char *p = ret;
memset(p, ' ', (size_t)bd->startspaces);
p += bd->startspaces;
memmove(p, bd->textstart, (size_t)bd->textlen);
p += bd->textlen;
memset(p, ' ', (size_t)bd->endspaces);
*(p + bd->endspaces) = NUL;
String ret = { .data = xmalloc(size + 1) };
memset(ret.data, ' ', (size_t)bd->startspaces);
ret.size += (size_t)bd->startspaces;
memmove(ret.data + ret.size, bd->textstart, (size_t)bd->textlen);
ret.size += (size_t)bd->textlen;
memset(ret.data + ret.size, ' ', (size_t)bd->endspaces);
ret.size += (size_t)bd->endspaces;
ret.data[ret.size] = NUL;
return ret;
}
@@ -2326,24 +2328,22 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
for (linenr_T lnum = p1.lnum; lnum <= p2.lnum; lnum++) {
char *akt = NULL;
String akt = STRING_INIT;
if (region_type == kMTLineWise) {
akt = xstrdup(ml_get(lnum));
} else if (region_type == kMTBlockWise) {
if (region_type == kMTBlockWise) {
struct block_def bd;
block_prep(&oa, &bd, lnum, false);
akt = block_def2str(&bd);
} else if (p1.lnum < lnum && lnum < p2.lnum) {
akt = xstrdup(ml_get(lnum));
} else if (region_type == kMTLineWise || (p1.lnum < lnum && lnum < p2.lnum)) {
akt = cbuf_to_string(ml_get(lnum), (size_t)ml_get_len(lnum));
} else {
struct block_def bd;
charwise_block_prep(p1, p2, &bd, lnum, inclusive);
akt = block_def2str(&bd);
}
assert(akt != NULL);
tv_list_append_allocated_string(rettv->vval.v_list, akt);
assert(akt.data != NULL);
tv_list_append_allocated_string(rettv->vval.v_list, akt.data);
}
// getregionpos() may change curbuf and virtual_op
@@ -6949,12 +6949,18 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
assert(len <= INT_MAX);
tv_list_alloc_ret(rettv, 2);
tv_list_append_string(rettv->vval.v_list, word, (ssize_t)len);
tv_list_append_string(rettv->vval.v_list,
(attr == HLF_SPB
? "bad" : (attr == HLF_SPR
? "rare" : (attr == HLF_SPL
? "local" : (attr == HLF_SPC
? "caps" : NULL)))), -1);
switch (attr) {
case HLF_SPB:
tv_list_append_string(rettv->vval.v_list, S_LEN("bad")); break;
case HLF_SPR:
tv_list_append_string(rettv->vval.v_list, S_LEN("rare")); break;
case HLF_SPL:
tv_list_append_string(rettv->vval.v_list, S_LEN("local")); break;
case HLF_SPC:
tv_list_append_string(rettv->vval.v_list, S_LEN("caps")); break;
default:
tv_list_append_string(rettv->vval.v_list, NULL, -1); break;
}
}
/// "spellsuggest()" function

View File

@@ -238,11 +238,15 @@ static void get_framelayout(const frame_T *fr, list_T *l, bool outer)
if (fr->fr_layout == FR_LEAF) {
if (fr->fr_win != NULL) {
tv_list_append_string(fr_list, "leaf", -1);
tv_list_append_string(fr_list, S_LEN("leaf"));
tv_list_append_number(fr_list, fr->fr_win->handle);
}
} else {
tv_list_append_string(fr_list, fr->fr_layout == FR_ROW ? "row" : "col", -1);
if (fr->fr_layout == FR_ROW) {
tv_list_append_string(fr_list, S_LEN("row"));
} else {
tv_list_append_string(fr_list, S_LEN("col"));
}
list_T *const win_list = tv_list_alloc(kListLenUnknown);
tv_list_append_list(fr_list, win_list);

View File

@@ -1215,7 +1215,7 @@ void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
// The yanked text contents.
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
for (size_t i = 0; i < reg->y_size; i++) {
tv_list_append_string(list, reg->y_array[i].data, -1);
tv_list_append_string(list, reg->y_array[i].data, (int)reg->y_array[i].size);
}
tv_list_set_lock(list, VAR_FIXED);
tv_dict_add_list(dict, S_LEN("regcontents"), list);
@@ -2344,7 +2344,7 @@ void *get_reg_contents(int regname, int flags)
if (flags & kGRegList) {
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
for (size_t i = 0; i < reg->y_size; i++) {
tv_list_append_string(list, reg->y_array[i].data, -1);
tv_list_append_string(list, reg->y_array[i].data, (int)reg->y_array[i].size);
}
return list;