diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /src/nvim/strings.c | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-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.c | 129 |
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 |