diff options
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.c | 43 |
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; } |