diff options
| author | Paul Eggert | 2018-08-21 02:16:50 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-21 02:38:53 -0700 |
| commit | d6a497dd887cdbb35c5b4e2929e83962ba708159 (patch) | |
| tree | 9f0441f9fe88419b71e568b05ef7f7bea0a0ff06 /src/floatfns.c | |
| parent | 77fc2725985b4e5ef977ae6930835c7f0771c61c (diff) | |
| download | emacs-d6a497dd887cdbb35c5b4e2929e83962ba708159.tar.gz emacs-d6a497dd887cdbb35c5b4e2929e83962ba708159.zip | |
Avoid libgmp aborts by imposing limits
libgmp calls ‘abort’ when given numbers too big for its
internal data structures. The numeric limit is large and
platform-dependent; with 64-bit GMP 6.1.2 it is around
2**2**37. Work around the problem by refusing to call libgmp
functions with arguments that would cause an abort. With luck
libgmp will have a better way to do this in the future.
Also, introduce a variable integer-width that lets the user
control how large bignums can be. This currently defaults
to 2**16, i.e., it allows bignums up to 2**2**16. This
should be enough for ordinary computation, and should
help Emacs to avoid thrashing or hanging.
Problem noted by Pip Cet (Bug#32463#71).
* doc/lispref/numbers.texi, etc/NEWS:
Document recent bignum changes, including this one.
Improve documentation for bitwise operations, in the light
of bignums.
* src/alloc.c (make_number): Enforce integer-width.
(integer_overflow): New function.
(xrealloc_for_gmp, xfree_for_gmp):
Move here from emacs.c, as it's memory allocation.
(init_alloc): Initialize GMP here, rather than in emacs.c.
(integer_width): New var.
* src/data.c (GMP_NLIMBS_MAX, NLIMBS_LIMIT): New constants.
(emacs_mpz_size, emacs_mpz_mul)
(emacs_mpz_mul_2exp, emacs_mpz_pow_ui): New functions.
(arith_driver, Fash, expt_integer): Use them.
(expt_integer): New function, containing integer code
that was out of place in floatfns.c.
(check_bignum_size, xmalloc_for_gmp): Remove.
* src/emacs.c (main): Do not initialize GMP here.
* src/floatfns.c (Fexpt): Use expt_integer, which
now contains integer code moved from here.
* src/lisp.h (GMP_NUMB_BITS): Define if gmp.h doesn’t.
Diffstat (limited to 'src/floatfns.c')
| -rw-r--r-- | src/floatfns.c | 24 |
1 files changed, 1 insertions, 23 deletions
diff --git a/src/floatfns.c b/src/floatfns.c index 7c52a0a9a20..ea9000b90a0 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -210,29 +210,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | |||
| 210 | /* Common Lisp spec: don't promote if both are integers, and if the | 210 | /* Common Lisp spec: don't promote if both are integers, and if the |
| 211 | result is not fractional. */ | 211 | result is not fractional. */ |
| 212 | if (INTEGERP (arg1) && NATNUMP (arg2)) | 212 | if (INTEGERP (arg1) && NATNUMP (arg2)) |
| 213 | { | 213 | return expt_integer (arg1, arg2); |
| 214 | unsigned long exp; | ||
| 215 | if (TYPE_RANGED_FIXNUMP (unsigned long, arg2)) | ||
| 216 | exp = XFIXNUM (arg2); | ||
| 217 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (arg2) | ||
| 218 | && mpz_fits_ulong_p (XBIGNUM (arg2)->value)) | ||
| 219 | exp = mpz_get_ui (XBIGNUM (arg2)->value); | ||
| 220 | else | ||
| 221 | xsignal3 (Qrange_error, build_string ("expt"), arg1, arg2); | ||
| 222 | |||
| 223 | mpz_t val; | ||
| 224 | mpz_init (val); | ||
| 225 | if (FIXNUMP (arg1)) | ||
| 226 | { | ||
| 227 | mpz_set_intmax (val, XFIXNUM (arg1)); | ||
| 228 | mpz_pow_ui (val, val, exp); | ||
| 229 | } | ||
| 230 | else | ||
| 231 | mpz_pow_ui (val, XBIGNUM (arg1)->value, exp); | ||
| 232 | Lisp_Object res = make_number (val); | ||
| 233 | mpz_clear (val); | ||
| 234 | return res; | ||
| 235 | } | ||
| 236 | 214 | ||
| 237 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); | 215 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); |
| 238 | } | 216 | } |