summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/vasprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/vasprintf.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/vasprintf.c156
1 files changed, 98 insertions, 58 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/vasprintf.c b/Build/source/libs/mpfr/mpfr-src/src/vasprintf.c
index 6a6ec03c73e..e37167e033a 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/vasprintf.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/vasprintf.c
@@ -1,7 +1,7 @@
/* mpfr_vasnprintf_aux -- helper function for the formatted output functions
(printf functions family).
-Copyright 2007-2018 Free Software Foundation, Inc.
+Copyright 2007-2019 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -18,7 +18,7 @@ License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
-http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
+https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
/* If the number of output characters is larger than INT_MAX, the
@@ -33,11 +33,22 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
So, for the time being, we return a negative value and set the erange
flag, and set errno to EOVERFLOW in POSIX system. */
-/* Note: Due to limitations from the C standard and GMP, if
- size_t < unsigned int (which is allowed by the C standard but unlikely
- to occur on any platform), the behavior is undefined for output that
- would reach SIZE_MAX = (size_t) -1 (if the result cannot be delivered,
- there should be an assertion failure, but this could not be tested). */
+/* Notes about limitations on some platforms:
+
+ Due to limitations from the C standard and GMP, if size_t < unsigned int
+ (which is allowed by the C standard but unlikely to occur on any
+ platform), the behavior is undefined for output that would reach
+ SIZE_MAX = (size_t) -1 (if the result cannot be delivered, there should
+ be an assertion failure, but this could not be tested).
+
+ The stdarg(3) Linux man page says:
+ On some systems, va_end contains a closing '}' matching a '{' in
+ va_start, so that both macros must occur in the same function,
+ and in a way that allows this.
+ However, the only requirement from ISO C is that both macros must be
+ invoked in the same function (MPFR uses va_copy instead of va_start,
+ but the requirement is the same). Here, MPFR just follows ISO C.
+*/
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -248,6 +259,8 @@ specinfo_is_valid (struct printf_spec spec)
}
}
+/* Note: additional flags should be added to the MPFR_PREC_ARG code
+ for gmp_asprintf (when supported). */
static const char *
parse_flags (const char *format, struct printf_spec *specinfo)
{
@@ -683,20 +696,31 @@ buffer_sandwich (struct string_buffer *b, char *str, size_t len,
else
{
const size_t step = 3;
- const size_t size = len + tz;
- const size_t r = size % step == 0 ? step : size % step;
- const size_t q = size % step == 0 ? size / step - 1 : size / step;
- const size_t fullsize = size + q;
- size_t i;
+ size_t size, q, r, fullsize;
+
+ /* check that len + tz does not overflow */
+ if (len > (size_t) -1 - tz)
+ return 1;
+ size = len + tz; /* number of digits */
MPFR_ASSERTD (size > 0);
+ q = (size - 1) / step; /* number of separators C */
+ r = ((size - 1) % step) + 1; /* number of digits in the leftmost block */
+
+ /* check that size + q does not overflow */
+ if (size > (size_t) -1 - q)
+ return 1;
+
+ fullsize = size + q; /* number of digits and separators */
+
if (buffer_incr_len (b, fullsize))
return 1;
if (b->size != 0)
{
char *oldcurr;
+ size_t i;
MPFR_ASSERTD (*b->curr == '\0');
MPFR_ASSERTN (b->size < ((size_t) -1) - fullsize);
@@ -705,11 +729,21 @@ buffer_sandwich (struct string_buffer *b, char *str, size_t len,
MPFR_DBGRES (oldcurr = b->curr);
- /* first R significant digits */
- memcpy (b->curr, str, r);
+ /* first r significant digits (leftmost block) */
+ if (r <= len)
+ {
+ memcpy (b->curr, str, r);
+ str += r;
+ len -= r;
+ }
+ else
+ {
+ MPFR_ASSERTD (r > len);
+ memcpy (b->curr, str, len);
+ memset (b->curr + len, '0', r - len);
+ len = 0;
+ }
b->curr += r;
- str += r;
- len -= r;
/* blocks of thousands. Warning: STR might end in the middle of a block */
for (i = 0; i < q; ++i)
@@ -722,6 +756,7 @@ buffer_sandwich (struct string_buffer *b, char *str, size_t len,
{
memcpy (b->curr, str, step);
len -= step;
+ str += step;
}
else
/* last digits in STR, fill up thousand block with zeros */
@@ -736,7 +771,6 @@ buffer_sandwich (struct string_buffer *b, char *str, size_t len,
memset (b->curr, '0', step);
b->curr += step;
- str += step;
}
MPFR_ASSERTD (b->curr - oldcurr == fullsize);
@@ -1920,8 +1954,14 @@ sprnt_fp (struct string_buffer *buf, mpfr_srcptr p,
/* integral part (may also be "nan" or "inf") */
MPFR_ASSERTN (np.ip_ptr != NULL); /* never empty */
if (MPFR_UNLIKELY (np.thousands_sep))
- buffer_sandwich (buf, np.ip_ptr, np.ip_size, np.ip_trailing_zeros,
- np.thousands_sep);
+ {
+ if (buffer_sandwich (buf, np.ip_ptr, np.ip_size, np.ip_trailing_zeros,
+ np.thousands_sep))
+ {
+ buf->len = -1;
+ goto clear_and_exit;
+ }
+ }
else
{
buffer_cat (buf, np.ip_ptr, np.ip_size);
@@ -1978,7 +2018,7 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt,
struct string_buffer buf;
int nbchar;
- /* informations on the conversion specification filled by the parser */
+ /* information on the conversion specification filled by the parser */
struct printf_spec spec;
/* flag raised when previous part of fmt need to be processed by
gmp_vsnprintf */
@@ -2182,7 +2222,7 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt,
/* output mpfr_prec_t variable */
{
char *s;
- char format[MPFR_PREC_FORMAT_SIZE + 6]; /* see examples below */
+ char format[MPFR_PREC_FORMAT_SIZE + 12]; /* e.g. "%0#+ -'*.*ld\0" */
size_t length;
mpfr_prec_t prec;
@@ -2194,14 +2234,14 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt,
start = fmt;
/* construct format string, like "%*.*hd" "%*.*d" or "%*.*ld" */
- format[0] = '%';
- format[1] = '*';
- format[2] = '.';
- format[3] = '*';
- format[4] = '\0';
- strcat (format, MPFR_PREC_FORMAT_TYPE);
- format[4 + MPFR_PREC_FORMAT_SIZE] = spec.spec;
- format[5 + MPFR_PREC_FORMAT_SIZE] = '\0';
+ sprintf (format, "%%%s%s%s%s%s%s*.*" MPFR_PREC_FORMAT_TYPE "%c",
+ spec.pad == '0' ? "0" : "",
+ spec.alt ? "#" : "",
+ spec.showsign ? "+" : "",
+ spec.space ? " " : "",
+ spec.left ? "-" : "",
+ spec.group ? "'" : "",
+ spec.spec);
length = gmp_asprintf (&s, format, spec.width, spec.prec, prec);
MPFR_ASSERTN (length >= 0); /* guaranteed by GMP 6 */
buffer_cat (&buf, s, length);
@@ -2246,44 +2286,42 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt,
va_end (ap2);
- if (buf.len > INT_MAX) /* overflow */
- buf.len = -1;
+ if (buf.len == -1 || buf.len > INT_MAX) /* overflow */
+ goto overflow;
- if (buf.len != -1)
- {
- nbchar = buf.len;
- MPFR_ASSERTD (nbchar >= 0);
+ nbchar = buf.len;
+ MPFR_ASSERTD (nbchar >= 0);
- if (ptr != NULL) /* implement mpfr_vasprintf */
+ if (ptr != NULL) /* implement mpfr_vasprintf */
+ {
+ MPFR_ASSERTD (nbchar == strlen (buf.start));
+ *ptr = (char *) mpfr_reallocate_func (buf.start, buf.size, nbchar + 1);
+ }
+ else if (size != 0) /* implement mpfr_vsnprintf */
+ {
+ if (nbchar < size)
{
- MPFR_ASSERTD (nbchar == strlen (buf.start));
- *ptr = (char *)
- mpfr_reallocate_func (buf.start, buf.size, nbchar + 1);
+ strncpy (Buf, buf.start, nbchar);
+ Buf[nbchar] = '\0';
}
- else if (size > 0) /* implement mpfr_vsnprintf */
+ else
{
- if (nbchar < size)
- {
- strncpy (Buf, buf.start, nbchar);
- Buf[nbchar] = '\0';
- }
- else
- {
- strncpy (Buf, buf.start, size - 1);
- Buf[size-1] = '\0';
- }
- mpfr_free_func (buf.start, buf.size);
+ strncpy (Buf, buf.start, size - 1);
+ Buf[size-1] = '\0';
}
-
- MPFR_SAVE_EXPO_FREE (expo);
- return nbchar; /* return the number of characters that would have
- been written had 'size' been sufficiently large,
- not counting the terminating null character */
+ mpfr_free_func (buf.start, buf.size);
}
+ MPFR_SAVE_EXPO_FREE (expo);
+ return nbchar; /* return the number of characters that would have
+ been written had 'size' been sufficiently large,
+ not counting the terminating null character */
+
error:
+ va_end (ap2);
if (buf.len == -1) /* overflow */
{
+ overflow:
MPFR_LOG_MSG (("Overflow\n", 0));
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_ERANGE);
#ifdef EOVERFLOW
@@ -2293,8 +2331,10 @@ mpfr_vasnprintf_aux (char **ptr, char *Buf, size_t size, const char *fmt,
}
MPFR_SAVE_EXPO_FREE (expo);
- *ptr = NULL;
- mpfr_free_func (buf.start, buf.size);
+ if (ptr != NULL) /* implement mpfr_vasprintf */
+ *ptr = NULL;
+ if (ptr != NULL || size != 0)
+ mpfr_free_func (buf.start, buf.size);
return -1;
}