Commit: patch 9.2.0031: Inefficient use of ga_concat()

1 view
Skip to first unread message

Christian Brabandt

unread,
12:31 PM (3 hours ago) 12:31 PM
to vim...@googlegroups.com
patch 9.2.0031: Inefficient use of ga_concat()

Commit: https://github.com/vim/vim/commit/ed202035b1904c84d92adb76d7e1a95b7540e048
Author: John Marriott <basi...@internode.on.net>
Date: Thu Feb 19 17:25:27 2026 +0000

patch 9.2.0031: Inefficient use of ga_concat()

Problem: Inefficient use of ga_concat()
Solution: Use ga_concat_len() when the length is already known to avoid
use of strlen() (John Marriott).

closes: #19422

Co-authored-by: Hirohito Higashi <h.eas...@gmail.com>
Signed-off-by: John Marriott <basi...@internode.on.net>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/clientserver.c b/src/clientserver.c
index 028da5c06..3d801bbf0 100644
--- a/src/clientserver.c
+++ b/src/clientserver.c
@@ -674,12 +674,16 @@ build_drop_cmd(
int i;
char_u *inicmd = NULL;
char_u *p;
- char_u *cdp;
+ string_T cdp;
char_u *cwd;
// reset wildignore temporarily
- const char *wig[] =
- { "<CR><C-\><C-N>:let g:_wig=&wig|set wig=",
- "<C-\><C-N>:let &wig=g:_wig|unlet g:_wig<CR>"};
+# define STRING_INIT(s) \
+ {(char_u *)(s), STRLEN_LITERAL(s)}
+ const string_T wig[] = {
+ STRING_INIT("<CR><C-\><C-N>:let g:_wig=&wig|set wig="),
+ STRING_INIT("<C-\><C-N>:let &wig=g:_wig|unlet g:_wig<CR>")
+ };
+# undef STRING_INIT

if (filec > 0 && filev[0][0] == '+')
{
@@ -700,7 +704,7 @@ build_drop_cmd(
vim_free(cwd);
return NULL;
}
- cdp = vim_strsave_escaped_ext(cwd,
+ cdp.string = vim_strsave_escaped_ext(cwd,
# ifdef BACKSLASH_IN_FILENAME
(char_u *)"", // rem_backslash() will tell what chars to escape
# else
@@ -708,20 +712,20 @@ build_drop_cmd(
# endif
'\', TRUE);
vim_free(cwd);
- if (cdp == NULL)
+ if (cdp.string == NULL)
return NULL;
+ cdp.length = STRLEN(cdp.string);
ga_init2(&ga, 1, 100);
- ga_concat(&ga, (char_u *)"<C-\><C-N>:cd ");
- ga_concat(&ga, cdp);
+ GA_CONCAT_LITERAL(&ga, "<C-\><C-N>:cd ");
+ ga_concat_len(&ga, cdp.string, cdp.length);
// reset wildignorecase temporarily
- ga_concat(&ga, (char_u *)wig[0]);
+ ga_concat_len(&ga, wig[0].string, wig[0].length);

// Call inputsave() so that a prompt for an encryption key works.
- ga_concat(&ga, (char_u *)
- "<CR><C-\><C-N>:if exists('*inputsave')|call inputsave()|endif|");
+ GA_CONCAT_LITERAL(&ga, "<CR><C-\><C-N>:if exists('*inputsave')|call inputsave()|endif|");
if (tabs)
- ga_concat(&ga, (char_u *)"tab ");
- ga_concat(&ga, (char_u *)"drop");
+ GA_CONCAT_LITERAL(&ga, "tab ");
+ GA_CONCAT_LITERAL(&ga, "drop");
for (i = 0; i < filec; i++)
{
// On Unix the shell has already expanded the wildcards, don't want to
@@ -739,16 +743,15 @@ build_drop_cmd(
vim_free(ga.ga_data);
return NULL;
}
- ga_concat(&ga, (char_u *)" ");
+ GA_CONCAT_LITERAL(&ga, " ");
ga_concat(&ga, p);
vim_free(p);
}
- ga_concat(&ga, (char_u *)
- "|if exists('*inputrestore')|call inputrestore()|endif<CR>");
+ GA_CONCAT_LITERAL(&ga, "|if exists('*inputrestore')|call inputrestore()|endif<CR>");

// The :drop commands goes to Insert mode when 'insertmode' is set, use
// CTRL-\ CTRL-N again.
- ga_concat(&ga, (char_u *)"<C-\><C-N>");
+ GA_CONCAT_LITERAL(&ga, "<C-\><C-N>");

// Switch back to the correct current directory (prior to temporary path
// switch) unless 'autochdir' is set, in which case it will already be
@@ -761,34 +764,34 @@ build_drop_cmd(
// cd -
// endif
// endif
- ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|");
+ GA_CONCAT_LITERAL(&ga, ":if !exists('+acd')||!&acd|if haslocaldir()|");
# ifdef MSWIN
// in case :set shellslash is set, need to normalize the directory separators
// '/' is not valid in a filename so replacing '/' by '\' should be safe
- ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd()->tr('/','\') ==# '");
+ GA_CONCAT_LITERAL(&ga, "cd -|lcd -|elseif getcwd()->tr('/','\') ==# '");
# else
- ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '");
+ GA_CONCAT_LITERAL(&ga, "cd -|lcd -|elseif getcwd() ==# '");
# endif
- ga_concat(&ga, cdp);
- ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>");
- vim_free(cdp);
+ ga_concat_len(&ga, cdp.string, cdp.length);
+ GA_CONCAT_LITERAL(&ga, "'|cd -|endif|endif<CR>");
+ vim_free(cdp.string);
// reset wildignorecase
- ga_concat(&ga, (char_u *)wig[1]);
+ ga_concat_len(&ga, wig[1].string, wig[1].length);

if (sendReply)
- ga_concat(&ga, (char_u *)":call SetupRemoteReplies()<CR>");
- ga_concat(&ga, (char_u *)":");
+ GA_CONCAT_LITERAL(&ga, ":call SetupRemoteReplies()<CR>");
+ GA_CONCAT_LITERAL(&ga, ":");
if (inicmd != NULL)
{
// Can't use <CR> after "inicmd", because a "startinsert" would cause
// the following commands to be inserted as text. Use a "|",
// hopefully "inicmd" does allow this...
ga_concat(&ga, inicmd);
- ga_concat(&ga, (char_u *)"|");
+ GA_CONCAT_LITERAL(&ga, "|");
}
// Bring the window to the foreground, goto Insert mode when 'im' set and
// clear command line.
- ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>");
+ GA_CONCAT_LITERAL(&ga, "cal foreground()|if &im|star|en|redr|f<CR>");
ga_append(&ga, NUL);
return ga.ga_data;
}
diff --git a/src/json.c b/src/json.c
index d70d3b6c5..8b0b050b8 100644
--- a/src/json.c
+++ b/src/json.c
@@ -96,6 +96,7 @@ json_encode_lsp_msg(typval_T *val)
{
garray_T ga;
garray_T lspga;
+ size_t IObufflen;

ga_init2(&ga, 1, 4000);
if (json_encode_gap(&ga, val, 0) == FAIL)
@@ -104,10 +105,10 @@ json_encode_lsp_msg(typval_T *val)

ga_init2(&lspga, 1, 4000);
// Header according to LSP specification.
- vim_snprintf((char *)IObuff, IOSIZE,
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
"Content-Length: %u

",
ga.ga_len - 1);
- ga_concat(&lspga, IObuff);
+ ga_concat_len(&lspga, IObuff, IObufflen);
ga_concat_len(&lspga, ga.ga_data, ga.ga_len);
ga_clear(&ga);
return lspga.ga_data;
@@ -145,7 +146,7 @@ write_string(garray_T *gap, char_u *str)

if (res == NULL)
{
- ga_concat(gap, (char_u *)"\"\"");
+ GA_CONCAT_LITERAL(gap, "\"\"");
return;
}

@@ -199,16 +200,21 @@ write_string(garray_T *gap, char_u *str)
ga_append(gap, c);
break;
default:
- vim_snprintf((char *)numbuf, NUMBUFLEN, "\u%04lx",
- (long)c);
- ga_concat(gap, numbuf);
+ {
+ size_t numbuflen;
+
+ numbuflen = vim_snprintf_safelen((char *)numbuf,
+ sizeof(numbuf), "\u%04lx", (long)c);
+ ga_concat_len(gap, numbuf, numbuflen);
+ }
}

res += 1;
}
else
{
- int l = utf_ptr2len(res);
+ int l = utf_ptr2len(res);
+ size_t numbuflen;

if (l > 1)
{
@@ -222,8 +228,9 @@ write_string(garray_T *gap, char_u *str)
ga_concat_len(gap, from, res - from);
from = res + 1;

- numbuf[utf_char2bytes(0xFFFD, numbuf)] = NUL;
- ga_concat(gap, numbuf);
+ numbuflen = utf_char2bytes(0xFFFD, numbuf);
+ numbuf[numbuflen] = NUL;
+ ga_concat_len(gap, numbuf, numbuflen);

res += l;
}
@@ -276,8 +283,8 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_BOOL:
switch ((long)val->vval.v_number)
{
- case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
- case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
+ case VVAL_FALSE: GA_CONCAT_LITERAL(gap, "false"); break;
+ case VVAL_TRUE: GA_CONCAT_LITERAL(gap, "true"); break;
}
break;

@@ -289,14 +296,18 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
// empty item
break;
// FALLTHROUGH
- case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break;
+ case VVAL_NULL: GA_CONCAT_LITERAL(gap, "null"); break;
}
break;

case VAR_NUMBER:
- vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld",
- (varnumber_T)val->vval.v_number);
- ga_concat(gap, numbuf);
+ {
+ size_t numbuflen;
+
+ numbuflen = vim_snprintf_safelen((char *)numbuf, sizeof(numbuf),
+ "%lld", (varnumber_T)val->vval.v_number);
+ ga_concat_len(gap, numbuf, numbuflen);
+ }
break;

case VAR_STRING:
@@ -318,17 +329,19 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_BLOB:
b = val->vval.v_blob;
if (b == NULL || b->bv_ga.ga_len == 0)
- ga_concat(gap, (char_u *)"[]");
+ GA_CONCAT_LITERAL(gap, "[]");
else
{
ga_append(gap, '[');
for (i = 0; i < b->bv_ga.ga_len; i++)
{
+ size_t numbuflen;
+
if (i > 0)
- ga_concat(gap, (char_u *)",");
- vim_snprintf((char *)numbuf, NUMBUFLEN, "%d",
- blob_get(b, i));
- ga_concat(gap, numbuf);
+ GA_CONCAT_LITERAL(gap, ",");
+ numbuflen = vim_snprintf_safelen((char *)numbuf, sizeof(numbuf),
+ "%d", blob_get(b, i));
+ ga_concat_len(gap, numbuf, numbuflen);
}
ga_append(gap, ']');
}
@@ -337,11 +350,11 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_LIST:
l = val->vval.v_list;
if (l == NULL)
- ga_concat(gap, (char_u *)"[]");
+ GA_CONCAT_LITERAL(gap, "[]");
else
{
if (l->lv_copyID == copyID)
- ga_concat(gap, (char_u *)"[]");
+ GA_CONCAT_LITERAL(gap, "[]");
else
{
listitem_T *li;
@@ -373,11 +386,11 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_TUPLE:
tuple = val->vval.v_tuple;
if (tuple == NULL)
- ga_concat(gap, (char_u *)"[]");
+ GA_CONCAT_LITERAL(gap, "[]");
else
{
if (tuple->tv_copyID == copyID)
- ga_concat(gap, (char_u *)"[]");
+ GA_CONCAT_LITERAL(gap, "[]");
else
{
int len = TUPLE_LEN(tuple);
@@ -409,11 +422,11 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_DICT:
d = val->vval.v_dict;
if (d == NULL)
- ga_concat(gap, (char_u *)"{}");
+ GA_CONCAT_LITERAL(gap, "{}");
else
{
if (d->dv_copyID == copyID)
- ga_concat(gap, (char_u *)"{}");
+ GA_CONCAT_LITERAL(gap, "{}");
else
{
int first = TRUE;
@@ -451,20 +464,22 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_FLOAT:
#if defined(HAVE_MATH_H)
if (isnan(val->vval.v_float))
- ga_concat(gap, (char_u *)"NaN");
+ GA_CONCAT_LITERAL(gap, "NaN");
else if (isinf(val->vval.v_float))
{
if (val->vval.v_float < 0.0)
- ga_concat(gap, (char_u *)"-Infinity");
+ GA_CONCAT_LITERAL(gap, "-Infinity");
else
- ga_concat(gap, (char_u *)"Infinity");
+ GA_CONCAT_LITERAL(gap, "Infinity");
}
else
#endif
{
- vim_snprintf((char *)numbuf, NUMBUFLEN, "%g",
- val->vval.v_float);
- ga_concat(gap, numbuf);
+ size_t numbuflen;
+
+ numbuflen = vim_snprintf_safelen((char *)numbuf, sizeof(numbuf),
+ "%g", val->vval.v_float);
+ ga_concat_len(gap, numbuf, numbuflen);
}
break;
case VAR_UNKNOWN:
@@ -612,9 +627,11 @@ json_decode_string(js_read_T *reader, typval_T *res, int quote)
if (res != NULL)
{
char_u buf[NUMBUFLEN];
+ size_t buflen;

- buf[utf_char2bytes((int)nr, buf)] = NUL;
- ga_concat(&ga, buf);
+ buflen = utf_char2bytes((int)nr, buf);
+ buf[buflen] = NUL;
+ ga_concat_len(&ga, buf, buflen);
}
break;
default:
diff --git a/src/list.c b/src/list.c
index c3d7b5a2b..253b1be9f 100644
--- a/src/list.c
+++ b/src/list.c
@@ -1466,7 +1466,7 @@ list2string(typval_T *tv, int copyID, int restore_copyID)
}

typedef struct join_S {
- char_u *s;
+ string_T s;
char_u *tofree;
} join_T;

@@ -1482,37 +1482,39 @@ list_join_inner(
{
int i;
join_T *p;
- int len;
int sumlen = 0;
int first = TRUE;
char_u *tofree;
char_u numbuf[NUMBUFLEN];
listitem_T *item;
- char_u *s;
+ string_T s;
+ size_t seplen;

// Stringify each item in the list.
CHECK_LIST_MATERIALIZE(l);
for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
{
- s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
+ s.string = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
echo_style, restore_copyID, !echo_style);
- if (s == NULL)
+ if (s.string == NULL)
return FAIL;

- len = (int)STRLEN(s);
- sumlen += len;
+ s.length = STRLEN(s.string);
+ sumlen += (int)s.length;

(void)ga_grow(join_gap, 1);
p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
- if (tofree != NULL || s != numbuf)
+ if (tofree != NULL || s.string != numbuf)
{
- p->s = s;
+ p->s.string = s.string;
+ p->s.length = s.length;
p->tofree = tofree;
}
else
{
- p->s = vim_strnsave(s, len);
- p->tofree = p->s;
+ p->s.string = vim_strnsave(s.string, s.length);
+ p->s.length = s.length;
+ p->tofree = p->s.string;
}

line_breakcheck();
@@ -1522,8 +1524,9 @@ list_join_inner(

// Allocate result buffer with its total size, avoid re-allocation and
// multiple copy operations. Add 2 for a tailing ']' and NUL.
+ seplen = STRLEN(sep);
if (join_gap->ga_len >= 2)
- sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
+ sumlen += (int)seplen * (join_gap->ga_len - 1);
if (ga_grow(gap, sumlen + 2) == FAIL)
return FAIL;

@@ -1532,11 +1535,11 @@ list_join_inner(
if (first)
first = FALSE;
else
- ga_concat(gap, sep);
+ ga_concat_len(gap, sep, seplen);
p = ((join_T *)join_gap->ga_data) + i;

- if (p->s != NULL)
- ga_concat(gap, p->s);
+ if (p->s.string != NULL)
+ ga_concat_len(gap, p->s.string, p->s.length);
line_breakcheck();
}

@@ -1836,8 +1839,11 @@ f_list2str(typval_T *argvars, typval_T *rettv)

FOR_ALL_LIST_ITEMS(l, li)
{
- buf[(*char2bytes)(tv_get_number(&li->li_tv), buf)] = NUL;
- ga_concat(&ga, buf);
+ size_t buflen;
+
+ buflen = (size_t)(*char2bytes)(tv_get_number(&li->li_tv), buf);
+ buf[buflen] = NUL;
+ ga_concat_len(&ga, buf, buflen);
}
ga_append(&ga, NUL);
}
diff --git a/src/macros.h b/src/macros.h
index 3e2c1c568..9007b5b37 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -424,6 +424,7 @@
#define GA_GROW_FAILS(gap, n) unlikely((((gap)->ga_maxlen - (gap)->ga_len < (n)) ? ga_grow_inner((gap), (n)) : OK) == FAIL)
// Inlined version of ga_grow() with optimized condition that it succeeds.
#define GA_GROW_OK(gap, n) likely((((gap)->ga_maxlen - (gap)->ga_len < (n)) ? ga_grow_inner((gap), (n)) : OK) == OK)
+#define GA_CONCAT_LITERAL(gap, s) ga_concat_len((gap), (char_u *)(s), STRLEN_LITERAL(s))

#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
diff --git a/src/testing.c b/src/testing.c
index dd8dc8e51..75e5edfc7 100644
--- a/src/testing.c
+++ b/src/testing.c
@@ -21,7 +21,6 @@
static void
prepare_assert_error(garray_T *gap)
{
- char buf[NUMBUFLEN];
char_u *sname = estack_sfile(ESTACK_NONE);

ga_init2(gap, 1, 100);
@@ -29,15 +28,18 @@ prepare_assert_error(garray_T *gap)
{
ga_concat(gap, sname);
if (SOURCING_LNUM > 0)
- ga_concat(gap, (char_u *)" ");
+ GA_CONCAT_LITERAL(gap, " ");
}
if (SOURCING_LNUM > 0)
{
- sprintf(buf, "line %ld", (long)SOURCING_LNUM);
- ga_concat(gap, (char_u *)buf);
+ char buf[NUMBUFLEN];
+ size_t buflen;
+
+ buflen = vim_snprintf_safelen(buf, sizeof(buf), "line %ld", (long)SOURCING_LNUM);
+ ga_concat_len(gap, (char_u *)buf, buflen);
}
if (sname != NULL || SOURCING_LNUM > 0)
- ga_concat(gap, (char_u *)": ");
+ GA_CONCAT_LITERAL(gap, ": ");
vim_free(sname);
}

@@ -54,28 +56,31 @@ ga_concat_esc(garray_T *gap, char_u *p, int clen)
{
mch_memmove(buf, p, clen);
buf[clen] = NUL;
- ga_concat(gap, buf);
+ ga_concat_len(gap, buf, clen);
return;
}

switch (*p)
{
- case BS: ga_concat(gap, (char_u *)"\b"); break;
- case ESC: ga_concat(gap, (char_u *)"\e"); break;
- case FF: ga_concat(gap, (char_u *)"\f"); break;
- case NL: ga_concat(gap, (char_u *)"\n"); break;
- case TAB: ga_concat(gap, (char_u *)"\t"); break;
- case CAR: ga_concat(gap, (char_u *)"\r"); break;
- case '\': ga_concat(gap, (char_u *)"\\"); break;
+ case BS: GA_CONCAT_LITERAL(gap, "\b"); break;
+ case ESC: GA_CONCAT_LITERAL(gap, "\e"); break;
+ case FF: GA_CONCAT_LITERAL(gap, "\f"); break;
+ case NL: GA_CONCAT_LITERAL(gap, "\n"); break;
+ case TAB: GA_CONCAT_LITERAL(gap, "\t"); break;
+ case CAR: GA_CONCAT_LITERAL(gap, "\r"); break;
+ case '\': GA_CONCAT_LITERAL(gap, "\\"); break;
default:
- if (*p < ' ' || *p == 0x7f)
- {
- vim_snprintf((char *)buf, NUMBUFLEN, "\x%02x", *p);
- ga_concat(gap, buf);
- }
- else
- ga_append(gap, *p);
- break;
+ if (*p < ' ' || *p == 0x7f)
+ {
+ size_t buflen;
+
+ buflen = vim_snprintf_safelen((char *)buf, sizeof(buf),
+ "\x%02x", *p);
+ ga_concat_len(gap, buf, buflen);
+ }
+ else
+ ga_append(gap, *p);
+ break;
}
}

@@ -91,11 +96,12 @@ ga_concat_shorten_esc(garray_T *gap, char_u *str)
int c;
int clen;
char_u buf[NUMBUFLEN];
+ size_t buflen;
int same_len;

if (str == NULL)
{
- ga_concat(gap, (char_u *)"NULL");
+ GA_CONCAT_LITERAL(gap, "NULL");
return;
}

@@ -112,12 +118,13 @@ ga_concat_shorten_esc(garray_T *gap, char_u *str)
}
if (same_len > 20)
{
- ga_concat(gap, (char_u *)"\[");
+ GA_CONCAT_LITERAL(gap, "\[");
ga_concat_esc(gap, p, clen);
- ga_concat(gap, (char_u *)" occurs ");
- vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len);
- ga_concat(gap, buf);
- ga_concat(gap, (char_u *)" times]");
+ GA_CONCAT_LITERAL(gap, " occurs ");
+ buflen = vim_snprintf_safelen((char *)buf, sizeof(buf),
+ "%d", same_len);
+ ga_concat_len(gap, buf, buflen);
+ GA_CONCAT_LITERAL(gap, " times]");
p = s;
}
else
@@ -154,15 +161,15 @@ fill_assert_error(
{
ga_concat(gap, echo_string(opt_msg_tv, &tofree, numbuf, 0));
vim_free(tofree);
- ga_concat(gap, (char_u *)": ");
+ GA_CONCAT_LITERAL(gap, ": ");
}

if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH)
- ga_concat(gap, (char_u *)"Pattern ");
+ GA_CONCAT_LITERAL(gap, "Pattern ");
else if (atype == ASSERT_NOTEQUAL)
- ga_concat(gap, (char_u *)"Expected not equal to ");
+ GA_CONCAT_LITERAL(gap, "Expected not equal to ");
else
- ga_concat(gap, (char_u *)"Expected ");
+ GA_CONCAT_LITERAL(gap, "Expected ");
if (exp_str == NULL)
{
// When comparing dictionaries, drop the items that are equal, so that
@@ -227,29 +234,30 @@ fill_assert_error(
else
{
if (atype == ASSERT_FAILS)
- ga_concat(gap, (char_u *)"'");
+ GA_CONCAT_LITERAL(gap, "'");
ga_concat_shorten_esc(gap, exp_str);
if (atype == ASSERT_FAILS)
- ga_concat(gap, (char_u *)"'");
+ GA_CONCAT_LITERAL(gap, "'");
}
if (atype != ASSERT_NOTEQUAL)
{
if (atype == ASSERT_MATCH)
- ga_concat(gap, (char_u *)" does not match ");
+ GA_CONCAT_LITERAL(gap, " does not match ");
else if (atype == ASSERT_NOTMATCH)
- ga_concat(gap, (char_u *)" does match ");
+ GA_CONCAT_LITERAL(gap, " does match ");
else
- ga_concat(gap, (char_u *)" but got ");
+ GA_CONCAT_LITERAL(gap, " but got ");
ga_concat_shorten_esc(gap, tv2string(got_tv, &tofree, numbuf, 0));
vim_free(tofree);

if (omitted != 0)
{
- char buf[100];
+ char buf[100];
+ size_t buflen;

- vim_snprintf(buf, 100, " - %d equal item%s omitted",
- omitted, omitted == 1 ? "" : "s");
- ga_concat(gap, (char_u *)buf);
+ buflen = vim_snprintf_safelen(buf, sizeof(buf),
+ " - %d equal item%s omitted", omitted, omitted == 1 ? "" : "s");
+ ga_concat_len(gap, (char_u *)buf, buflen);
}
}

@@ -368,9 +376,9 @@ assert_beeps(typval_T *argvars, int no_beep)
{
prepare_assert_error(&ga);
if (no_beep)
- ga_concat(&ga, (char_u *)"command did beep: ");
+ GA_CONCAT_LITERAL(&ga, "command did beep: ");
else
- ga_concat(&ga, (char_u *)"command did not beep: ");
+ GA_CONCAT_LITERAL(&ga, "command did not beep: ");
ga_concat(&ga, cmd);
assert_error(&ga);
ga_clear(&ga);
@@ -427,16 +435,18 @@ assert_equalfile(typval_T *argvars)
char line1[200];
char line2[200];
int lineidx = 0;
+ size_t IObufflen;

if (fname1 == NULL || fname2 == NULL)
return 0;

IObuff[0] = NUL;
+ IObufflen = 0;
fd1 = mch_fopen((char *)fname1, READBIN);
if (fd1 == NULL)
{
- vim_snprintf((char *)IObuff, IOSIZE, (char *)e_cant_read_file_str,
- fname1);
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
+ (char *)e_cant_read_file_str, fname1);
}
else
{
@@ -444,8 +454,8 @@ assert_equalfile(typval_T *argvars)
if (fd2 == NULL)
{
fclose(fd1);
- vim_snprintf((char *)IObuff, IOSIZE, (char *)e_cant_read_file_str,
- fname2);
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
+ (char *)e_cant_read_file_str, fname2);
}
else
{
@@ -460,12 +470,16 @@ assert_equalfile(typval_T *argvars)
if (c1 == EOF)
{
if (c2 != EOF)
+ {
STRCPY(IObuff, "first file is shorter");
+ IObufflen = 21;
+ }
break;
}
else if (c2 == EOF)
{
STRCPY(IObuff, "second file is shorter");
+ IObufflen = 22;
break;
}
else
@@ -475,9 +489,8 @@ assert_equalfile(typval_T *argvars)
++lineidx;
if (c1 != c2)
{
- vim_snprintf((char *)IObuff, IOSIZE,
- "difference at byte %ld, line %ld",
- count, linecount);
+ IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
+ "difference at byte %ld, line %ld", count, linecount);
break;
}
}
@@ -499,7 +512,7 @@ assert_equalfile(typval_T *argvars)
}
}

- if (IObuff[0] != NUL)
+ if (IObufflen > 0)
{
garray_T ga;
prepare_assert_error(&ga);
@@ -510,21 +523,21 @@ assert_equalfile(typval_T *argvars)

ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0));
vim_free(tofree);
- ga_concat(&ga, (char_u *)": ");
+ GA_CONCAT_LITERAL(&ga, ": ");
}
- ga_concat(&ga, IObuff);
+ ga_concat_len(&ga, IObuff, IObufflen);
if (lineidx > 0)
{
line1[lineidx] = NUL;
line2[lineidx] = NUL;
- ga_concat(&ga, (char_u *)" after \"");
- ga_concat(&ga, (char_u *)line1);
+ GA_CONCAT_LITERAL(&ga, " after \"");
+ ga_concat_len(&ga, (char_u *)line1, lineidx);
if (STRCMP(line1, line2) != 0)
{
- ga_concat(&ga, (char_u *)"\" vs \"");
- ga_concat(&ga, (char_u *)line2);
+ GA_CONCAT_LITERAL(&ga, "\" vs \"");
+ ga_concat_len(&ga, (char_u *)line2, lineidx);
}
- ga_concat(&ga, (char_u *)"\"");
+ GA_CONCAT_LITERAL(&ga, "\"");
}
assert_error(&ga);
ga_clear(&ga);
@@ -576,7 +589,7 @@ f_assert_exception(typval_T *argvars, typval_T *rettv)
if (*get_vim_var_str(VV_EXCEPTION) == NUL)
{
prepare_assert_error(&ga);
- ga_concat(&ga, (char_u *)"v:exception is not set");
+ GA_CONCAT_LITERAL(&ga, "v:exception is not set");
assert_error(&ga);
ga_clear(&ga);
rettv->vval.v_number = 1;
@@ -630,7 +643,7 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
if (called_emsg == called_emsg_before)
{
prepare_assert_error(&ga);
- ga_concat(&ga, (char_u *)"command did not fail: ");
+ GA_CONCAT_LITERAL(&ga, "command did not fail: ");
assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
@@ -749,7 +762,7 @@ f_assert_fails(typval_T *argvars, typval_T *rettv)
}
fill_assert_error(&ga, &argvars[2], expected_str,
&argvars[error_found_index], &actual_tv, ASSERT_FAILS);
- ga_concat(&ga, (char_u *)": ");
+ GA_CONCAT_LITERAL(&ga, ": ");
assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
diff --git a/src/version.c b/src/version.c
index 5df5e5dcc..b929dea0f 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 */
+/**/
+ 31,
/**/
30,
/**/
Reply all
Reply to author
Forward
0 new messages