commit 940d5c239b088fe0e994a220b4d524ddb44760e9
parent 9aa936d8929161cba360788c2f9d67b263c8d0b6
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sun, 22 Feb 2026 07:43:59 +0800
Merge pull request #37991 from zeertzjq/vim-9.2.0031
vim-patch:9.2.{0031,0041}: Inefficient use of ga_concat()
Diffstat:
12 files changed, 125 insertions(+), 111 deletions(-)
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
@@ -4059,7 +4059,7 @@ static int copy_substring_from_pos(pos_T *start, pos_T *end, char **match, pos_T
ga_concat_len(&ga, start_ptr, (size_t)segment_len);
if (!is_single_line) {
if (exacttext) {
- ga_concat_len(&ga, S_LEN("\\n"));
+ GA_CONCAT_LITERAL(&ga, "\\n");
} else {
ga_append(&ga, '\n');
}
@@ -4073,7 +4073,7 @@ static int copy_substring_from_pos(pos_T *start, pos_T *end, char **match, pos_T
ga_grow(&ga, linelen + 2);
ga_concat_len(&ga, line, (size_t)linelen);
if (exacttext) {
- ga_concat_len(&ga, S_LEN("\\n"));
+ GA_CONCAT_LITERAL(&ga, "\\n");
} else {
ga_append(&ga, '\n');
}
diff --git a/src/nvim/errors.h b/src/nvim/errors.h
@@ -74,7 +74,7 @@ EXTERN const char e_noroom[] INIT(= N_("E36: Not enough room"));
EXTERN const char e_notmp[] INIT(= N_("E483: Can't get temp file name"));
EXTERN const char e_notopen[] INIT(= N_("E484: Can't open file %s"));
EXTERN const char e_notopen_2[] INIT(= N_("E484: Can't open file %s: %s"));
-EXTERN const char e_notread[] INIT(= N_("E485: Can't read file %s"));
+EXTERN const char e_cant_read_file_str[] INIT(= N_("E485: Can't read file %s"));
EXTERN const char e_null[] INIT(= N_("E38: Null argument"));
EXTERN const char e_number_exp[] INIT(= N_("E39: Number expected"));
EXTERN const char e_openerrf[] INIT(= N_("E40: Can't open errorfile %s"));
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
@@ -124,7 +124,7 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
const char *const partial_self_msg = _("partial self dictionary");
for (size_t i = 0; i < kv_size(*mpstack); i++) {
if (i != 0) {
- ga_concat_len(&msg_ga, S_LEN(", "));
+ GA_CONCAT_LITERAL(&msg_ga, ", ");
}
MPConvStackVal v = kv_A(*mpstack, i);
switch (v.type) {
@@ -296,7 +296,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
do { \
const char *const buf_ = (buf); \
if (buf_ == NULL) { \
- ga_concat_len(gap, S_LEN("''")); \
+ GA_CONCAT_LITERAL(gap, "''"); \
} else { \
const size_t len_ = (len); \
ga_grow(gap, (int)(2 + len_ + memcnt(buf_, '\'', len_))); \
@@ -321,13 +321,13 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const blob_T *const blob_ = (blob); \
const int len_ = (len); \
if (len_ == 0) { \
- ga_concat_len(gap, S_LEN("0z")); \
+ GA_CONCAT_LITERAL(gap, "0z"); \
} else { \
/* Allocate space for "0z", the two hex chars per byte, and a */ \
/* "." separator after every eight hex chars. */ \
/* Example: "0z00112233.44556677.8899" */ \
ga_grow(gap, 2 + 2 * len_ + (len_ - 1) / 4); \
- ga_concat_len(gap, S_LEN("0z")); \
+ GA_CONCAT_LITERAL(gap, "0z"); \
char numbuf[NUMBUFLEN]; \
for (int i_ = 0; i_ < len_; i_++) { \
if (i_ > 0 && (i_ & 3) == 0) { \
@@ -343,8 +343,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
do { \
char numbuf[NUMBUFLEN]; \
- vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t)(num)); \
- ga_concat(gap, numbuf); \
+ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
+ "%" PRId64, (int64_t)(num)); \
+ ga_concat_len(gap, numbuf, numbuflen); \
} while (0)
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
@@ -352,20 +353,21 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const float_T flt_ = (flt); \
switch (xfpclassify(flt_)) { \
case FP_NAN: { \
- ga_concat_len(gap, S_LEN("str2float('nan')")); \
+ GA_CONCAT_LITERAL(gap, "str2float('nan')"); \
break; \
} \
case FP_INFINITE: { \
if (flt_ < 0) { \
ga_append(gap, '-'); \
} \
- ga_concat_len(gap, S_LEN("str2float('inf')")); \
+ GA_CONCAT_LITERAL(gap, "str2float('inf')"); \
break; \
} \
default: { \
char numbuf[NUMBUFLEN]; \
- vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \
- ga_concat(gap, numbuf); \
+ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
+ "%g", flt_); \
+ ga_concat_len(gap, numbuf, numbuflen); \
} \
} \
} while (0)
@@ -375,10 +377,10 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
const char *const fun_ = (fun); \
if (fun_ == NULL) { \
internal_error("string(): NULL function name"); \
- ga_concat_len(gap, S_LEN("function(NULL")); \
+ GA_CONCAT_LITERAL(gap, "function(NULL"); \
} else { \
const char *const prefix_ = (prefix); \
- ga_concat_len(gap, S_LEN("function(")); \
+ GA_CONCAT_LITERAL(gap, "function("); \
const int name_off = gap->ga_len; \
ga_concat(gap, prefix_); \
TYPVAL_ENCODE_CONV_STRING(tv, fun_, strlen(fun_)); \
@@ -391,14 +393,14 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \
do { \
if ((len) != 0) { \
- ga_concat_len(gap, S_LEN(", ")); \
+ GA_CONCAT_LITERAL(gap, ", "); \
} \
} while (0)
#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) \
do { \
if ((ptrdiff_t)(len) != -1) { \
- ga_concat_len(gap, S_LEN(", ")); \
+ GA_CONCAT_LITERAL(gap, ", "); \
} \
} while (0)
@@ -406,7 +408,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
ga_append(gap, ')')
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
- ga_concat_len(gap, S_LEN("[]"))
+ GA_CONCAT_LITERAL(gap, "[]")
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
ga_append(gap, '[')
@@ -414,19 +416,19 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv)
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
- ga_concat_len(gap, S_LEN("{}"))
+ GA_CONCAT_LITERAL(gap, "{}")
#define TYPVAL_ENCODE_CHECK_BEFORE
#define TYPVAL_ENCODE_CONV_NIL(tv) \
- ga_concat_len(gap, S_LEN("v:null"))
+ GA_CONCAT_LITERAL(gap, "v:null")
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \
if (num) { \
- ga_concat_len(gap, S_LEN("v:true")); \
+ GA_CONCAT_LITERAL(gap, "v:true"); \
} else { \
- ga_concat_len(gap, S_LEN("v:false")); \
+ GA_CONCAT_LITERAL(gap, "v:false"); \
} \
} while (0)
@@ -441,10 +443,10 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
ga_append(gap, '}')
#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \
- ga_concat_len(gap, S_LEN(": "))
+ GA_CONCAT_LITERAL(gap, ": ")
#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \
- ga_concat_len(gap, S_LEN(", "))
+ GA_CONCAT_LITERAL(gap, ", ")
#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key)
@@ -552,15 +554,15 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#undef TYPVAL_ENCODE_CONV_NIL
#define TYPVAL_ENCODE_CONV_NIL(tv) \
- ga_concat_len(gap, S_LEN("null"))
+ GA_CONCAT_LITERAL(gap, "null")
#undef TYPVAL_ENCODE_CONV_BOOL
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \
if (num) { \
- ga_concat_len(gap, S_LEN("true")); \
+ GA_CONCAT_LITERAL(gap, "true"); \
} else { \
- ga_concat_len(gap, S_LEN("false")); \
+ GA_CONCAT_LITERAL(gap, "false"); \
} \
} while (0)
@@ -568,8 +570,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \
do { \
char numbuf[NUMBUFLEN]; \
- vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \
- ga_concat(gap, numbuf); \
+ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
+ "%" PRIu64, (num)); \
+ ga_concat_len(gap, numbuf, numbuflen); \
} while (0)
#undef TYPVAL_ENCODE_CONV_FLOAT
@@ -587,8 +590,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
} \
default: { \
char numbuf[NUMBUFLEN]; \
- vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%g", flt_); \
- ga_concat(gap, numbuf); \
+ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
+ "%g", flt_); \
+ ga_concat_len(gap, numbuf, numbuflen); \
break; \
} \
} \
@@ -620,7 +624,7 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const
{
const char *utf_buf = buf;
if (utf_buf == NULL) {
- ga_concat_len(gap, S_LEN("\"\""));
+ GA_CONCAT_LITERAL(gap, "\"\"");
} else {
size_t utf_len = len;
char *tofree = NULL;
@@ -749,17 +753,17 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const
const blob_T *const blob_ = (blob); \
const int len_ = (len); \
if (len_ == 0) { \
- ga_concat_len(gap, S_LEN("[]")); \
+ GA_CONCAT_LITERAL(gap, "[]"); \
} else { \
ga_append(gap, '['); \
char numbuf[NUMBUFLEN]; \
for (int i_ = 0; i_ < len_; i_++) { \
if (i_ > 0) { \
- ga_concat_len(gap, S_LEN(", ")); \
+ GA_CONCAT_LITERAL(gap, ", "); \
} \
- vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%d", \
- (int)tv_blob_get(blob_, i_)); \
- ga_concat(gap, numbuf); \
+ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), \
+ "%d", (int)tv_blob_get(blob_, i_)); \
+ ga_concat_len(gap, numbuf, numbuflen); \
} \
ga_append(gap, ']'); \
} \
diff --git a/src/nvim/eval/fs.c b/src/nvim/eval/fs.c
@@ -1307,7 +1307,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl
if (blob) {
if (read_blob(fd, rettv, offset, size) == FAIL) {
- semsg(_(e_notread), fname);
+ semsg(_(e_cant_read_file_str), fname);
}
fclose(fd);
return;
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
@@ -971,7 +971,7 @@ int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumb
}
typedef struct {
- char *s;
+ String s;
char *tofree;
} Join;
@@ -995,25 +995,26 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con
if (got_int) {
break;
}
- char *s;
- size_t len;
- s = encode_tv2echo(TV_LIST_ITEM_TV(item), &len);
- if (s == NULL) {
+ String s;
+ s.data = encode_tv2echo(TV_LIST_ITEM_TV(item), &s.size);
+ if (s.data == NULL) {
return FAIL;
}
- sumlen += len;
+ sumlen += s.size;
Join *const p = GA_APPEND_VIA_PTR(Join, join_gap);
- p->tofree = p->s = s;
+ p->s = s;
+ p->tofree = s.data;
line_breakcheck();
});
// Allocate result buffer with its total size, avoid re-allocation and
// multiple copy operations. Add 2 for a tailing ']' and NUL.
+ size_t seplen = strlen(sep);
if (join_gap->ga_len >= 2) {
- sumlen += strlen(sep) * (size_t)(join_gap->ga_len - 1);
+ sumlen += seplen * (size_t)(join_gap->ga_len - 1);
}
ga_grow(gap, (int)sumlen + 2);
@@ -1021,12 +1022,12 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con
if (first) {
first = false;
} else {
- ga_concat(gap, sep);
+ ga_concat_len(gap, sep, seplen);
}
const Join *const p = ((const Join *)join_gap->ga_data) + i;
- if (p->s != NULL) {
- ga_concat(gap, p->s);
+ if (p->s.data != NULL) {
+ ga_concat_len(gap, p->s.data, p->s.size);
}
line_breakcheck();
}
@@ -1106,8 +1107,10 @@ void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char buf[MB_MAXBYTES + 1];
TV_LIST_ITER_CONST(l, li, {
- buf[utf_char2bytes((int)tv_get_number(TV_LIST_ITEM_TV(li)), buf)] = NUL;
- ga_concat(&ga, buf);
+ const varnumber_T n = tv_get_number(TV_LIST_ITEM_TV(li));
+ const size_t buflen = (size_t)utf_char2bytes((int)n, buf);
+ buf[buflen] = NUL;
+ ga_concat_len(&ga, buf, buflen);
});
ga_append(&ga, NUL);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
@@ -1373,7 +1373,7 @@ static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char *cmd, b
READ_FILTER, false) != OK) {
if (!aborting()) {
msg_putchar('\n');
- semsg(_(e_notread), otmp);
+ semsg(_(e_cant_read_file_str), otmp);
}
goto error;
}
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
@@ -4,6 +4,7 @@
#include <stddef.h>
#include "nvim/garray_defs.h" // IWYU pragma: keep
+#include "nvim/macros_defs.h" // IWYU pragma: keep
#include "nvim/memory.h"
#define GA_EMPTY(ga_ptr) ((ga_ptr)->ga_len <= 0)
@@ -45,3 +46,5 @@
///
/// @param gap the garray to be freed
#define GA_DEEP_CLEAR_PTR(gap) GA_DEEP_CLEAR(gap, void *, FREE_PTR_PTR)
+
+#define GA_CONCAT_LITERAL(gap, s) ga_concat_len((gap), S_LEN(s))
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
@@ -3202,7 +3202,7 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
aborted = true;
} else if (c1 == K_SNR) {
- ga_concat_len(&line_ga, S_LEN("<SNR>"));
+ GA_CONCAT_LITERAL(&line_ga, "<SNR>");
} else {
if (cmod != 0) {
ga_append(&line_ga, K_SPECIAL);
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
@@ -415,7 +415,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
os_remove(tempname);
if (readlen != len) {
// unexpected read error
- semsg(_(e_notread), tempname);
+ semsg(_(e_cant_read_file_str), tempname);
xfree(tempname);
xfree(buffer);
return FAIL;
@@ -809,7 +809,7 @@ char *get_cmd_output(char *cmd, char *infile, int flags, size_t *ret_len)
fclose(fd);
os_remove(tempname);
if (i != len) {
- semsg(_(e_notread), tempname);
+ semsg(_(e_cant_read_file_str), tempname);
XFREE_CLEAR(buffer);
} else if (ret_len == NULL) {
// Change NUL into SOH, otherwise the string is truncated.
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
@@ -11587,9 +11587,9 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// grow indent for state->out
indent->ga_len -= 1;
if (state->out1) {
- ga_concat(indent, S_LEN("| "));
+ GA_CONCAT_LITERAL(indent, "| ");
} else {
- ga_concat(indent, S_LEN(" "));
+ GA_CONCAT_LITERAL(indent, " ");
}
ga_append(indent, NUL);
@@ -11597,7 +11597,7 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// replace last part of indent for state->out1
indent->ga_len -= 3;
- ga_concat(indent, S_LEN(" "));
+ GA_CONCAT_LITERAL(indent, " ");
ga_append(indent, NUL);
nfa_print_state2(debugf, state->out1, indent);
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
@@ -224,7 +224,7 @@ char *estack_sfile(estack_arg_T which)
"[%" PRIdLINENR "]", lnum);
}
if (idx != exestack.ga_len - 1) {
- ga_concat_len(&ga, S_LEN(".."));
+ GA_CONCAT_LITERAL(&ga, "..");
}
}
}
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
@@ -57,7 +57,6 @@ static const char e_calling_test_garbagecollect_now_while_v_testing_is_not_set[]
/// Prepare "gap" for an assert error and add the sourcing position.
static void prepare_assert_error(garray_T *gap)
{
- char buf[NUMBUFLEN];
char *sname = estack_sfile(ESTACK_NONE);
ga_init(gap, 1, 100);
@@ -68,11 +67,13 @@ static void prepare_assert_error(garray_T *gap)
}
}
if (SOURCING_LNUM > 0) {
- vim_snprintf(buf, ARRAY_SIZE(buf), "line %" PRId64, (int64_t)SOURCING_LNUM);
- ga_concat(gap, buf);
+ char buf[NUMBUFLEN];
+ size_t buflen = vim_snprintf_safelen(buf, ARRAY_SIZE(buf),
+ "line %" PRId64, (int64_t)SOURCING_LNUM);
+ ga_concat_len(gap, buf, buflen);
}
if (sname != NULL || SOURCING_LNUM > 0) {
- ga_concat(gap, ": ");
+ GA_CONCAT_LITERAL(gap, ": ");
}
xfree(sname);
}
@@ -87,29 +88,29 @@ static void ga_concat_esc(garray_T *gap, const char *p, int clen)
if (clen > 1) {
memmove(buf, p, (size_t)clen);
buf[clen] = NUL;
- ga_concat(gap, buf);
+ ga_concat_len(gap, buf, (size_t)clen);
return;
}
switch (*p) {
case BS:
- ga_concat(gap, "\\b"); break;
+ GA_CONCAT_LITERAL(gap, "\\b"); break;
case ESC:
- ga_concat(gap, "\\e"); break;
+ GA_CONCAT_LITERAL(gap, "\\e"); break;
case FF:
- ga_concat(gap, "\\f"); break;
+ GA_CONCAT_LITERAL(gap, "\\f"); break;
case NL:
- ga_concat(gap, "\\n"); break;
+ GA_CONCAT_LITERAL(gap, "\\n"); break;
case TAB:
- ga_concat(gap, "\\t"); break;
+ GA_CONCAT_LITERAL(gap, "\\t"); break;
case CAR:
- ga_concat(gap, "\\r"); break;
+ GA_CONCAT_LITERAL(gap, "\\r"); break;
case '\\':
- ga_concat(gap, "\\\\"); break;
+ GA_CONCAT_LITERAL(gap, "\\\\"); break;
default:
if ((uint8_t)(*p) < ' ' || *p == 0x7f) {
- vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p);
- ga_concat(gap, buf);
+ size_t buflen = vim_snprintf_safelen(buf, NUMBUFLEN, "\\x%02x", *p);
+ ga_concat_len(gap, buf, buflen);
} else {
ga_append(gap, (uint8_t)(*p));
}
@@ -125,7 +126,7 @@ static void ga_concat_shorten_esc(garray_T *gap, const char *str)
char buf[NUMBUFLEN];
if (str == NULL) {
- ga_concat(gap, "NULL");
+ GA_CONCAT_LITERAL(gap, "NULL");
return;
}
@@ -139,12 +140,12 @@ static void ga_concat_shorten_esc(garray_T *gap, const char *str)
s += clen;
}
if (same_len > 20) {
- ga_concat(gap, "\\[");
+ GA_CONCAT_LITERAL(gap, "\\[");
ga_concat_esc(gap, p, clen);
- ga_concat(gap, " occurs ");
- vim_snprintf(buf, NUMBUFLEN, "%d", same_len);
- ga_concat(gap, buf);
- ga_concat(gap, " times]");
+ GA_CONCAT_LITERAL(gap, " occurs ");
+ size_t buflen = vim_snprintf_safelen(buf, NUMBUFLEN, "%d", same_len);
+ ga_concat_len(gap, buf, buflen);
+ GA_CONCAT_LITERAL(gap, " times]");
p = s;
} else {
ga_concat_esc(gap, p, clen);
@@ -169,15 +170,15 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
char *tofree = encode_tv2echo(opt_msg_tv, NULL);
ga_concat(gap, tofree);
xfree(tofree);
- ga_concat(gap, ": ");
+ GA_CONCAT_LITERAL(gap, ": ");
}
if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
- ga_concat(gap, "Pattern ");
+ GA_CONCAT_LITERAL(gap, "Pattern ");
} else if (atype == ASSERT_NOTEQUAL) {
- ga_concat(gap, "Expected not equal to ");
+ GA_CONCAT_LITERAL(gap, "Expected not equal to ");
} else {
- ga_concat(gap, "Expected ");
+ GA_CONCAT_LITERAL(gap, "Expected ");
}
if (exp_str == NULL) {
@@ -232,21 +233,21 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
xfree(tofree);
} else {
if (atype == ASSERT_FAILS) {
- ga_concat(gap, "'");
+ GA_CONCAT_LITERAL(gap, "'");
}
ga_concat_shorten_esc(gap, exp_str);
if (atype == ASSERT_FAILS) {
- ga_concat(gap, "'");
+ GA_CONCAT_LITERAL(gap, "'");
}
}
if (atype != ASSERT_NOTEQUAL) {
if (atype == ASSERT_MATCH) {
- ga_concat(gap, " does not match ");
+ GA_CONCAT_LITERAL(gap, " does not match ");
} else if (atype == ASSERT_NOTMATCH) {
- ga_concat(gap, " does match ");
+ GA_CONCAT_LITERAL(gap, " does match ");
} else {
- ga_concat(gap, " but got ");
+ GA_CONCAT_LITERAL(gap, " but got ");
}
char *tofree = encode_tv2string(got_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
@@ -254,9 +255,10 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, const char *e
if (omitted != 0) {
char buf[100];
- vim_snprintf(buf, sizeof(buf), " - %d equal item%s omitted", omitted,
- omitted == 1 ? "" : "s");
- ga_concat(gap, buf);
+ size_t buflen = vim_snprintf_safelen(buf, sizeof(buf),
+ " - %d equal item%s omitted",
+ omitted, omitted == 1 ? "" : "s");
+ ga_concat_len(gap, buf, buflen);
}
}
@@ -354,9 +356,9 @@ static int assert_beeps(typval_T *argvars, bool no_beep)
garray_T ga;
prepare_assert_error(&ga);
if (no_beep) {
- ga_concat(&ga, "command did beep: ");
+ GA_CONCAT_LITERAL(&ga, "command did beep: ");
} else {
- ga_concat(&ga, "command did not beep: ");
+ GA_CONCAT_LITERAL(&ga, "command did not beep: ");
}
ga_concat(&ga, cmd);
assert_error(&ga);
@@ -400,17 +402,18 @@ static int assert_equalfile(typval_T *argvars)
}
IObuff[0] = NUL;
+ size_t IObufflen = 0;
FILE *const fd1 = os_fopen(fname1, READBIN);
char line1[200];
char line2[200];
ptrdiff_t lineidx = 0;
if (fd1 == NULL) {
- snprintf(IObuff, IOSIZE, e_notread, fname1);
+ IObufflen = vim_snprintf_safelen(IObuff, IOSIZE, e_cant_read_file_str, fname1);
} else {
FILE *const fd2 = os_fopen(fname2, READBIN);
if (fd2 == NULL) {
fclose(fd1);
- snprintf(IObuff, IOSIZE, e_notread, fname2);
+ IObufflen = vim_snprintf_safelen(IObuff, IOSIZE, e_cant_read_file_str, fname2);
} else {
int64_t linecount = 1;
for (int64_t count = 0;; count++) {
@@ -418,20 +421,21 @@ static int assert_equalfile(typval_T *argvars)
const int c2 = fgetc(fd2);
if (c1 == EOF) {
if (c2 != EOF) {
- xstrlcpy(IObuff, "first file is shorter", IOSIZE);
+ IObufflen = xstrlcpy(IObuff, "first file is shorter", IOSIZE);
}
break;
} else if (c2 == EOF) {
- xstrlcpy(IObuff, "second file is shorter", IOSIZE);
+ IObufflen = xstrlcpy(IObuff, "second file is shorter", IOSIZE);
break;
} else {
line1[lineidx] = (char)c1;
line2[lineidx] = (char)c2;
lineidx++;
if (c1 != c2) {
- snprintf(IObuff, IOSIZE,
- "difference at byte %" PRId64 ", line %" PRId64,
- count, linecount);
+ IObufflen
+ = vim_snprintf_safelen(IObuff, IOSIZE,
+ "difference at byte %" PRId64 ", line %" PRId64,
+ count, linecount);
break;
}
}
@@ -449,26 +453,26 @@ static int assert_equalfile(typval_T *argvars)
}
}
- if (IObuff[0] != NUL) {
+ if (IObufflen > 0) {
garray_T ga;
prepare_assert_error(&ga);
if (argvars[2].v_type != VAR_UNKNOWN) {
char *const tofree = encode_tv2echo(&argvars[2], NULL);
ga_concat(&ga, tofree);
xfree(tofree);
- ga_concat(&ga, ": ");
+ 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, " after \"");
- ga_concat(&ga, line1);
+ GA_CONCAT_LITERAL(&ga, " after \"");
+ ga_concat_len(&ga, line1, (size_t)lineidx);
if (strcmp(line1, line2) != 0) {
- ga_concat(&ga, "\" vs \"");
- ga_concat(&ga, line2);
+ GA_CONCAT_LITERAL(&ga, "\" vs \"");
+ ga_concat_len(&ga, line2, (size_t)lineidx);
}
- ga_concat(&ga, "\"");
+ GA_CONCAT_LITERAL(&ga, "\"");
}
assert_error(&ga);
ga_clear(&ga);
@@ -498,7 +502,7 @@ void f_assert_exception(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *const error = tv_get_string_chk(&argvars[0]);
if (*get_vim_var_str(VV_EXCEPTION) == NUL) {
prepare_assert_error(&ga);
- ga_concat(&ga, "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;
@@ -547,7 +551,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (called_emsg == called_emsg_before) {
prepare_assert_error(&ga);
- ga_concat(&ga, "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);
@@ -633,7 +637,7 @@ void f_assert_fails(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
fill_assert_error(&ga, &argvars[2], expected_str,
&argvars[error_found_index], &actual_tv, ASSERT_FAILS);
- ga_concat(&ga, ": ");
+ GA_CONCAT_LITERAL(&ga, ": ");
assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);