summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/inp_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/inp_str.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/inp_str.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/inp_str.c b/Build/source/libs/mpfr/mpfr-src/src/inp_str.c
index 8fae2e0fc87..e5b27ace139 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/inp_str.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/inp_str.c
@@ -1,7 +1,7 @@
/* mpfr_inp_str -- input a number in base BASE from stdio stream STREAM
and store the result in ROP
-Copyright 1999, 2001-2002, 2004, 2006-2019 Free Software Foundation, Inc.
+Copyright 1999, 2001-2002, 2004, 2006-2020 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -42,7 +42,7 @@ mpfr_inp_str (mpfr_ptr rop, FILE *stream, int base, mpfr_rnd_t rnd_mode)
str_size = 0;
nread = 0;
- /* Skip whitespace. */
+ /* Skip whitespace. EOF will be detected later. */
do
{
c = getc (stream);
@@ -54,33 +54,56 @@ mpfr_inp_str (mpfr_ptr rop, FILE *stream, int base, mpfr_rnd_t rnd_mode)
for (;;)
{
+ MPFR_ASSERTD (str_size < (size_t) -1);
if (str_size >= alloc_size)
{
size_t old_alloc_size = alloc_size;
- alloc_size = alloc_size * 3 / 2;
+ alloc_size = alloc_size / 2 * 3;
+ /* Handle overflow in unsigned integer arithmetic... */
+ if (MPFR_UNLIKELY (alloc_size <= old_alloc_size))
+ alloc_size = (size_t) -1;
+ MPFR_ASSERTD (str_size < alloc_size);
str = (unsigned char *)
mpfr_reallocate_func (str, old_alloc_size, alloc_size);
}
if (c == EOF || isspace (c))
break;
str[str_size++] = (unsigned char) c;
+ if (str_size == (size_t) -1)
+ break;
c = getc (stream);
}
ungetc (c, stream);
- /* number of characters read is nread + str_size - 1 */
+ if (MPFR_UNLIKELY (str_size == (size_t) -1 || str_size == 0 ||
+ (c == EOF && ! feof (stream))))
+ {
+ /* size_t overflow or I/O error */
+ retval = -1;
+ }
+ else
+ {
+ /* number of characters read is nread + str_size - 1 */
+
+ /* We exited the "for" loop by the first break instruction,
+ then necessarily str_size >= alloc_size was checked, so
+ now str_size < alloc_size. */
+ MPFR_ASSERTD (str_size < alloc_size);
- /* we can exit the for loop only by the break instruction,
- then necessarily str_size >= alloc_size was checked, so
- now str_size < alloc_size */
+ str[str_size] = '\0';
- str[str_size] = '\0';
+ retval = mpfr_set_str (rop, (char *) str, base, rnd_mode);
+ }
- retval = mpfr_set_str (rop, (char *) str, base, rnd_mode);
mpfr_free_func (str, alloc_size);
if (retval == -1)
return 0; /* error */
- return str_size + nread - 1;
+ MPFR_ASSERTD (nread >= 1);
+ str_size += nread - 1;
+ if (MPFR_UNLIKELY (str_size < nread - 1)) /* size_t overflow */
+ return 0; /* however rop has been set successfully */
+ else
+ return str_size;
}