From b4cb5fa610903492f89a70d0ae2d4565ddcd1228 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 19:20:07 +0100 Subject: vim-patch:7.4.2266 Problem: printf() test fails on Windows. "-inf" is not used. Solution: Check for Windows-specific values for "nan". Add sign to "inf" when appropriate. https://github.com/vim/vim/commit/9992237a3e791fbc0c1ebf743ece1b75e1488410 --- src/nvim/strings.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index d03970108b..47ee311bd4 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1209,9 +1209,10 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } if (fmt_spec == 'f' && abs_f > 1.0e307) { + const char inf_str[] = f < 0 ? "-inf" : "inf"; // avoid a buffer overflow - memmove(tmp, "inf", sizeof("inf")); - str_arg_l = sizeof("inf") - 1; + memmove(tmp, inf_str, sizeof(inf_str) - 1); + str_arg_l = sizeof(inf_str) - 1; } else { format[0] = '%'; int l = 1; @@ -1234,6 +1235,23 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); assert(str_arg_l < sizeof(tmp)); + // Be consistent: Change "1.#IND" to "nan" and + // "1.#INF" to "inf". + char *s = *tmp == '-' ? tmp + 1 : tmp; + if (STRNCMP(s, "1.#INF", 6) == 0) { + STRCPY(s, "inf"); + } else if (STRNCMP(s, "1.#IND", 6) == 0) { + STRCPY(s, "nan"); + } + // Remove sign before "nan" + if (STRNCMP(tmp, "-nan", 4) == 0) { + STRCPY(tmp, "nan"); + } + // Add sign before "inf" if needed. + if (isinf(f) == -1 && STRNCMP(tmp, "inf", 3) == 0) { + STRCPY(tmp, "-inf"); + } + if (remove_trailing_zeroes) { int i; char *tp; -- cgit From 6ca580be9bffcccc513bfce383a6e1f9f026614c Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 08:47:31 +0100 Subject: vim-patch:7.4.2280 Problem: printf() doesn't handle infinity float values correctly. Solution: Add a table with possible infinity values. (Dominique Pelle) https://github.com/vim/vim/commit/e999782e369999539a1783a7ebe4eadcc6da28a8 --- src/nvim/strings.c | 57 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 47ee311bd4..e8d70f2676 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -753,6 +753,22 @@ int vim_snprintf(char *str, size_t str_m, const char *fmt, ...) return str_l; } +// Return the representation of infinity for printf() function: +// "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". +static const char *infinity_str(bool positive, char fmt_spec, + int force_sign, int space_for_positive) +{ + static const char *table[] = { + "-inf", "inf", "+inf", " inf", + "-INF", "INF", "+INF", " INF" + }; + int idx = positive * (1 + force_sign + force_sign * space_for_positive); + if (ASCII_ISUPPER(fmt_spec)) { + idx += 4; + } + return table[idx]; +} + /// Write formatted value to the string /// @@ -1209,10 +1225,10 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } if (fmt_spec == 'f' && abs_f > 1.0e307) { - const char inf_str[] = f < 0 ? "-inf" : "inf"; - // avoid a buffer overflow - memmove(tmp, inf_str, sizeof(inf_str) - 1); - str_arg_l = sizeof(inf_str) - 1; + STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive)); + str_arg_l = STRLEN(tmp); + zero_padding = 0; } else { format[0] = '%'; int l = 1; @@ -1231,25 +1247,22 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); format[l + 1] = NUL; - assert(l + 1 < (int)sizeof(format)); - str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); - assert(str_arg_l < sizeof(tmp)); - // Be consistent: Change "1.#IND" to "nan" and - // "1.#INF" to "inf". - char *s = *tmp == '-' ? tmp + 1 : tmp; - if (STRNCMP(s, "1.#INF", 6) == 0) { - STRCPY(s, "inf"); - } else if (STRNCMP(s, "1.#IND", 6) == 0) { - STRCPY(s, "nan"); - } - // Remove sign before "nan" - if (STRNCMP(tmp, "-nan", 4) == 0) { - STRCPY(tmp, "nan"); - } - // Add sign before "inf" if needed. - if (isinf(f) == -1 && STRNCMP(tmp, "inf", 3) == 0) { - STRCPY(tmp, "-inf"); + if (isnan(f)) { + // Not a number: nan or NAN + STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); + str_arg_l = 3; + zero_padding = 0; + } else if (isinf(f)) { + STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive)); + str_arg_l = STRLEN(tmp); + zero_padding = 0; + } else { + // Regular float number + assert(l + 1 < (int)sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); } if (remove_trailing_zeroes) { -- cgit From cad9a76be28f2ee3bd2c48ae959243aa7cfdb02a Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 7 Mar 2017 21:05:02 +0100 Subject: vim-patch:7.4.2291 Problem: printf() handles floats wrong when there is a sign. Solution: Fix placing the sign. Add tests. (Dominique Pelle) https://github.com/vim/vim/commit/04186095346daa60e82e981dad114de2b641d672 --- src/nvim/strings.c | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index e8d70f2676..a2052423e2 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -925,7 +925,6 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - case 'F': fmt_spec = 'f'; break; default: break; } @@ -1202,6 +1201,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } case 'f': + case 'F': case 'e': case 'E': case 'g': @@ -1217,37 +1217,19 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, if (fmt_spec == 'g' || fmt_spec == 'G') { // can't use %g directly, cause it prints "1.0" as "1" if ((abs_f >= 0.001 && abs_f < 10000000.0) || abs_f == 0.0) { - fmt_spec = 'f'; + fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; } else { fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; } remove_trailing_zeroes = true; } - if (fmt_spec == 'f' && abs_f > 1.0e307) { + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0e307) { STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, force_sign, space_for_positive)); str_arg_l = STRLEN(tmp); zero_padding = 0; } else { - format[0] = '%'; - int l = 1; - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; - - // make sure we don't get more digits than we have room for - if (fmt_spec == 'f' && abs_f > 1.0) { - max_prec -= (size_t)log10(abs_f); - } - if (precision > max_prec) { - precision = max_prec; - } - l += snprintf(format + 1, sizeof(format) - 1, ".%d", - (int)precision); - } - format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); - format[l + 1] = NUL; - if (isnan(f)) { // Not a number: nan or NAN STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); @@ -1259,6 +1241,27 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, str_arg_l = STRLEN(tmp); zero_padding = 0; } else { + format[0] = '%'; + int l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; + + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); + } + if (precision > max_prec) { + precision = max_prec; + } + l += snprintf(format + l, sizeof(format) - 1, ".%d", + (int)precision); + } + format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); + format[l + 1] = NUL; + // Regular float number assert(l + 1 < (int)sizeof(format)); str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); @@ -1270,7 +1273,7 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, char *tp; // using %g or %G: remove superfluous zeroes - if (fmt_spec == 'f') { + if (fmt_spec == 'f' || fmt_spec == 'F') { tp = tmp + str_arg_l - 1; } else { tp = (char *)vim_strchr((char_u *)tmp, @@ -1312,6 +1315,12 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, } } } + if (zero_padding && min_field_width > str_arg_l + && (tmp[0] == '-' || force_sign)) { + // Padding 0's should be inserted after the sign. + number_of_zeros_to_pad = min_field_width - str_arg_l; + zero_padding_insertion_ind = 1; + } str_arg = tmp; break; } -- cgit From 3e33025133e1e77c7ad3b8670e06175b9757cf30 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Tue, 21 Mar 2017 22:48:01 +0100 Subject: strings: Fix problems found during code review --- src/nvim/strings.c | 71 +++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 38 deletions(-) (limited to 'src/nvim/strings.c') diff --git a/src/nvim/strings.c b/src/nvim/strings.c index a2052423e2..7ec2ea13f7 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -1224,49 +1224,44 @@ int vim_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap, remove_trailing_zeroes = true; } - if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0e307) { - STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, - force_sign, space_for_positive)); - str_arg_l = STRLEN(tmp); + if (isinf(f) + || (strchr("fF", fmt_spec) != NULL && abs_f > 1.0e307)) { + xstrlcpy(tmp, infinity_str(f > 0.0, fmt_spec, + force_sign, space_for_positive), + sizeof(tmp)); + str_arg_l = strlen(tmp); + zero_padding = 0; + } else if (isnan(f)) { + // Not a number: nan or NAN + memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4); + str_arg_l = 3; zero_padding = 0; } else { - if (isnan(f)) { - // Not a number: nan or NAN - STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan"); - str_arg_l = 3; - zero_padding = 0; - } else if (isinf(f)) { - STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, - force_sign, space_for_positive)); - str_arg_l = STRLEN(tmp); - zero_padding = 0; - } else { - format[0] = '%'; - int l = 1; - if (force_sign) { - format[l++] = space_for_positive ? ' ' : '+'; - } - if (precision_specified) { - size_t max_prec = TMP_LEN - 10; + format[0] = '%'; + size_t l = 1; + if (force_sign) { + format[l++] = space_for_positive ? ' ' : '+'; + } + if (precision_specified) { + size_t max_prec = TMP_LEN - 10; - // make sure we don't get more digits than we have room for - if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { - max_prec -= (size_t)log10(abs_f); - } - if (precision > max_prec) { - precision = max_prec; - } - l += snprintf(format + l, sizeof(format) - 1, ".%d", - (int)precision); + // make sure we don't get more digits than we have room for + if ((fmt_spec == 'f' || fmt_spec == 'F') && abs_f > 1.0) { + max_prec -= (size_t)log10(abs_f); } - format[l] = (char)(fmt_spec == 'F' ? 'f' : fmt_spec); - format[l + 1] = NUL; - - // Regular float number - assert(l + 1 < (int)sizeof(format)); - str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); - assert(str_arg_l < sizeof(tmp)); + if (precision > max_prec) { + precision = max_prec; + } + l += (size_t)snprintf(format + l, sizeof(format) - l, ".%d", + (int)precision); } + format[l] = fmt_spec == 'F' ? 'f' : fmt_spec; + format[l + 1] = NUL; + + // Regular float number + assert(l + 1 < sizeof(format)); + str_arg_l = (size_t)snprintf(tmp, sizeof(tmp), format, f); + assert(str_arg_l < sizeof(tmp)); if (remove_trailing_zeroes) { int i; -- cgit