aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/strings.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-11-19 22:57:13 +0000
committerJosh Rahm <joshuarahm@gmail.com>2024-11-19 22:57:13 +0000
commit9be89f131f87608f224f0ee06d199fcd09d32176 (patch)
tree11022dcfa9e08cb4ac5581b16734196128688d48 /src/nvim/strings.c
parentff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff)
parent88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff)
downloadrneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz
rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2
rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'src/nvim/strings.c')
-rw-r--r--src/nvim/strings.c129
1 files changed, 74 insertions, 55 deletions
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 16ae35272b..118abbae6d 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -12,6 +12,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/charset.h"
+#include "nvim/errors.h"
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
@@ -268,9 +269,9 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
}
if (do_special && find_cmdline_var(p, &l) >= 0) {
*d++ = '\\'; // insert backslash
- while (--l != SIZE_MAX) { // copy the var
- *d++ = *p++;
- }
+ memcpy(d, p, l); // copy the var
+ d += l;
+ p += l;
continue;
}
if (*p == '\\' && fish_like) {
@@ -332,7 +333,7 @@ void vim_strcpy_up(char *restrict dst, const char *restrict src)
while ((c = (uint8_t)(*src++)) != NUL) {
*dst++ = (char)(uint8_t)(c < 'a' || c > 'z' ? c : c - 0x20);
}
- *dst = '\0';
+ *dst = NUL;
}
// strncpy (NUL-terminated) plus vim_strup.
@@ -343,7 +344,7 @@ void vim_strncpy_up(char *restrict dst, const char *restrict src, size_t n)
while (n-- && (c = (uint8_t)(*src++)) != NUL) {
*dst++ = (char)(uint8_t)(c < 'a' || c > 'z' ? c : c - 0x20);
}
- *dst = '\0';
+ *dst = NUL;
}
// memcpy (does not NUL-terminate) plus vim_strup.
@@ -495,6 +496,20 @@ char *vim_strchr(const char *const string, const int c)
}
}
+// Sized version of strchr that can handle embedded NULs.
+// Adjusts n to the new size.
+char *strnchr(const char *p, size_t *n, int c)
+{
+ while (*n > 0) {
+ if (*p == c) {
+ return (char *)p;
+ }
+ p++;
+ (*n)--;
+ }
+ return NULL;
+}
+
// Sort an array of strings.
static int sort_compare(const void *s1, const void *s2)
@@ -628,12 +643,14 @@ static const void *tv_ptr(const typval_T *const tvs, int *const idxp)
#define OFF(attr) offsetof(union typval_vval_union, attr)
STATIC_ASSERT(OFF(v_string) == OFF(v_list)
&& OFF(v_string) == OFF(v_dict)
+ && OFF(v_string) == OFF(v_blob)
&& OFF(v_string) == OFF(v_partial)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_list)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_dict)
+ && sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_blob)
&& sizeof(tvs[0].vval.v_string) == sizeof(tvs[0].vval.v_partial),
- "Strings, dictionaries, lists and partials are expected to be pointers, "
- "so that all three of them can be accessed via v_string");
+ "Strings, Dictionaries, Lists, Blobs and Partials are expected to be pointers, "
+ "so that all of them can be accessed via v_string");
#undef OFF
const int idx = *idxp - 1;
if (tvs[idx].v_type == VAR_UNKNOWN) {
@@ -793,10 +810,10 @@ static int format_typeof(const char *type)
FUNC_ATTR_NONNULL_ALL
{
// allowed values: \0, h, l, L
- char length_modifier = '\0';
+ char length_modifier = NUL;
// current conversion specifier character
- char fmt_spec = '\0';
+ char fmt_spec = NUL;
// parse 'h', 'l', 'll' and 'z' length modifiers
if (*type == 'h' || *type == 'l' || *type == 'z') {
@@ -864,7 +881,7 @@ static int format_typeof(const char *type)
} else if (fmt_spec == 'd') {
// signed
switch (length_modifier) {
- case '\0':
+ case NUL:
case 'h':
// char and short arguments are passed as int.
return TYPE_INT;
@@ -878,7 +895,7 @@ static int format_typeof(const char *type)
} else {
// unsigned
switch (length_modifier) {
- case '\0':
+ case NUL:
case 'h':
return TYPE_UNSIGNEDINT;
case 'l':
@@ -1002,7 +1019,7 @@ static void format_overflow_error(const char *pstart)
enum { MAX_ALLOWED_STRING_WIDTH = 6400, };
-static int get_unsigned_int(const char *pstart, const char **p, unsigned *uj)
+static int get_unsigned_int(const char *pstart, const char **p, unsigned *uj, bool overflow_err)
{
*uj = (unsigned)(**p - '0');
(*p)++;
@@ -1013,8 +1030,12 @@ static int get_unsigned_int(const char *pstart, const char **p, unsigned *uj)
}
if (*uj > MAX_ALLOWED_STRING_WIDTH) {
- format_overflow_error(pstart);
- return FAIL;
+ if (overflow_err) {
+ format_overflow_error(pstart);
+ return FAIL;
+ } else {
+ *uj = MAX_ALLOWED_STRING_WIDTH;
+ }
}
return OK;
@@ -1049,7 +1070,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
p += n;
} else {
// allowed values: \0, h, l, L
- char length_modifier = '\0';
+ char length_modifier = NUL;
// variable for positional arg
int pos_arg = -1;
@@ -1075,7 +1096,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
// Positional argument
unsigned uj;
- if (get_unsigned_int(pstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(pstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1118,7 +1139,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
// Positional argument field width
unsigned uj;
- if (get_unsigned_int(arg + 1, &p, &uj) == FAIL) {
+ if (get_unsigned_int(arg + 1, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1144,7 +1165,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
const char *digstart = p;
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1165,7 +1186,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
// Parse precision
unsigned uj;
- if (get_unsigned_int(arg + 1, &p, &uj) == FAIL) {
+ if (get_unsigned_int(arg + 1, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1192,7 +1213,7 @@ static int parse_fmt_types(const char ***ap_types, int *num_posarg, const char *
const char *digstart = p;
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1440,7 +1461,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
int space_for_positive = 1;
// allowed values: \0, h, l, 2 (for ll), z, L
- char length_modifier = '\0';
+ char length_modifier = NUL;
// temporary buffer for simple numeric->string conversion
#define TMP_LEN 350 // 1e308 seems reasonable as the maximum printable
@@ -1465,7 +1486,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
size_t zero_padding_insertion_ind = 0;
// current conversion specifier character
- char fmt_spec = '\0';
+ char fmt_spec = NUL;
// buffer for 's' and 'S' specs
char *tofree = NULL;
@@ -1488,7 +1509,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
const char *digstart = p;
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1530,7 +1551,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
// Positional argument field width
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1539,15 +1560,19 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
p++;
}
- const int j = (tvs
- ? (int)tv_nr(tvs, &arg_idx)
- : (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
- &arg_cur, fmt),
- va_arg(ap, int)));
+ int j = (tvs
+ ? (int)tv_nr(tvs, &arg_idx)
+ : (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
+ &arg_cur, fmt),
+ va_arg(ap, int)));
if (j > MAX_ALLOWED_STRING_WIDTH) {
- format_overflow_error(digstart);
- goto error;
+ if (tvs != NULL) {
+ format_overflow_error(digstart);
+ goto error;
+ } else {
+ j = MAX_ALLOWED_STRING_WIDTH;
+ }
}
if (j >= 0) {
@@ -1562,12 +1587,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
const char *digstart = p;
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
- goto error;
- }
-
- if (uj > MAX_ALLOWED_STRING_WIDTH) {
- format_overflow_error(digstart);
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1585,12 +1605,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
const char *digstart = p;
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
- goto error;
- }
-
- if (uj > MAX_ALLOWED_STRING_WIDTH) {
- format_overflow_error(digstart);
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1604,7 +1619,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
// positional argument
unsigned uj;
- if (get_unsigned_int(digstart, &p, &uj) == FAIL) {
+ if (get_unsigned_int(digstart, &p, &uj, tvs != NULL) == FAIL) {
goto error;
}
@@ -1613,15 +1628,19 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
p++;
}
- const int j = (tvs
- ? (int)tv_nr(tvs, &arg_idx)
- : (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
- &arg_cur, fmt),
- va_arg(ap, int)));
+ int j = (tvs
+ ? (int)tv_nr(tvs, &arg_idx)
+ : (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
+ &arg_cur, fmt),
+ va_arg(ap, int)));
if (j > MAX_ALLOWED_STRING_WIDTH) {
- format_overflow_error(digstart);
- goto error;
+ if (tvs != NULL) {
+ format_overflow_error(digstart);
+ goto error;
+ } else {
+ j = MAX_ALLOWED_STRING_WIDTH;
+ }
}
if (j >= 0) {
@@ -1668,7 +1687,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
case 'o':
case 'x':
case 'X':
- if (tvs && length_modifier == '\0') {
+ if (tvs && length_modifier == NUL) {
length_modifier = 'L';
}
}
@@ -1789,7 +1808,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
} else if (fmt_spec == 'd') {
// signed
switch (length_modifier) {
- case '\0':
+ case NUL:
arg = (tvs
? (int)tv_nr(tvs, &arg_idx)
: (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
@@ -1835,7 +1854,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
} else {
// unsigned
switch (length_modifier) {
- case '\0':
+ case NUL:
uarg = (tvs
? (unsigned)tv_nr(tvs, &arg_idx)
: (skip_to_arg(ap_types, ap_start, &ap, &arg_idx,
@@ -2222,7 +2241,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
if (str_m > 0) {
// make sure the string is nul-terminated even at the expense of
// overwriting the last character (shouldn't happen, but just in case)
- str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
+ str[str_l <= str_m - 1 ? str_l : str_m - 1] = NUL;
}
if (tvs != NULL