diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2021-04-23 01:07:07 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2021-04-23 01:07:07 +0000 |
commit | 6caef48658118fdb8b661c9679ee19bcc54865d1 (patch) | |
tree | 19fa57a9000ed9b32c2192d72a92c0c0f85dc68b /src | |
parent | 2b410ca84bc1cae337c0c8f8a39e28a1fc20747a (diff) | |
download | mpfr-6caef48658118fdb8b661c9679ee19bcc54865d1.tar.gz |
Fixed bug in mpfr_get_str_ndigits.
* src/get_str.c: use MPFR_SAVE_EXPO_MARK / MPFR_SAVE_EXPO_FREE to fix
2 issues in mpfr_get_str_ndigits: the inexact flag could be raised
(bug reported by Pierre Chatelier[*]); undefined behavior in a very
reduced exponent range.
* tests/tget_str.c: check the above issues in the tests.
[*] https://sympa.inria.fr/sympa/arc/mpfr/2021-04/msg00000.html
git-svn-id: https://scm.gforge.inria.fr/anonscm/svn/mpfr/trunk@14488 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src')
-rw-r--r-- | src/get_str.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/get_str.c b/src/get_str.c index f9e4d779c..11c85f946 100644 --- a/src/get_str.c +++ b/src/get_str.c @@ -2484,6 +2484,8 @@ mpfr_ceil_mul (mpfr_exp_t e, int beta, int i) size_t mpfr_get_str_ndigits (int b, mpfr_prec_t p) { + MPFR_SAVE_EXPO_DECL (expo); + MPFR_ASSERTN (2 <= b && b <= 62); /* deal first with power of two bases, since even for those, mpfr_ceil_mul @@ -2497,17 +2499,26 @@ mpfr_get_str_ndigits (int b, mpfr_prec_t p) return 1 + (p + k - 2) / k; } + MPFR_SAVE_EXPO_MARK (expo); + /* the value returned by mpfr_ceil_mul is guaranteed to be 1 + ceil(p*log(2)/log(b)) for p < 186564318007 (it returns one more for p=186564318007 and b=7 or 49) */ MPFR_STAT_STATIC_ASSERT (MPFR_PREC_BITS >= 64 || MPFR_PREC_BITS <= 32); + if #if MPFR_PREC_BITS >= 64 /* 64-bit numbers are supported by the C implementation, so that we can use the large constant below. If MPFR_PREC_BITS <= 32, the condition is always satisfied, so that we do not need any test. */ - if (MPFR_LIKELY (p < 186564318007)) + (MPFR_LIKELY (p < 186564318007)) +#else + (1) #endif - return 1 + mpfr_ceil_mul (IS_POW2(b) ? p - 1 : p, b, 1); + { + size_t ret = 1 + mpfr_ceil_mul (IS_POW2(b) ? p - 1 : p, b, 1); + MPFR_SAVE_EXPO_FREE (expo); + return ret; + } /* Now p is large and b is not a power of two. The code below works for any value of p and b, as long as b is not a power of two. Indeed, in such a @@ -2541,6 +2552,8 @@ mpfr_get_str_ndigits (int b, mpfr_prec_t p) mpfr_clear (d); mpfr_clear (u); } + + MPFR_SAVE_EXPO_FREE (expo); return 1 + ret; } } |