diff options
| author | Paul Eggert | 2019-06-04 08:13:20 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-06-04 08:34:15 -0700 |
| commit | 7f4558e3d9edbdee6901e5fbcd4a4072f49ec5b9 (patch) | |
| tree | a709f4f82777f6a5e2c16e7d417ba59b74e7b430 /src | |
| parent | dd7bc5de3f59237f21e1c4b70f0ba97549ea1fb4 (diff) | |
| download | emacs-7f4558e3d9edbdee6901e5fbcd4a4072f49ec5b9.tar.gz emacs-7f4558e3d9edbdee6901e5fbcd4a4072f49ec5b9.zip | |
Always allow at least double-precision bignums
Without this fix, Emacs can get into a tight loop reporting
a range error when calculating timestamps.
* doc/lispref/numbers.texi (Integer Basics):
* src/alloc.c (syms_of_alloc): Document this.
* src/bignum.c (make_bignum_bits): Always allow bignums
of at least twice the width of (u)intmax_t.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 6 | ||||
| -rw-r--r-- | src/bignum.c | 7 |
2 files changed, 8 insertions, 5 deletions
diff --git a/src/alloc.c b/src/alloc.c index 5c5b56d02e9..64aaa8acdfa 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -7369,9 +7369,9 @@ The time is in seconds as a floating point value. */); | |||
| 7369 | doc: /* Accumulated number of garbage collections done. */); | 7369 | doc: /* Accumulated number of garbage collections done. */); |
| 7370 | 7370 | ||
| 7371 | DEFVAR_INT ("integer-width", integer_width, | 7371 | DEFVAR_INT ("integer-width", integer_width, |
| 7372 | doc: /* Maximum number of bits in bignums. | 7372 | doc: /* Maximum number N of bits in safely-calculated integers. |
| 7373 | Integers outside the fixnum range are limited to absolute values less | 7373 | Integers with absolute values less than 2**N do not signal a range error. |
| 7374 | than 2**N, where N is this variable's value. N should be nonnegative. */); | 7374 | N should be nonnegative. */); |
| 7375 | 7375 | ||
| 7376 | defsubr (&Scons); | 7376 | defsubr (&Scons); |
| 7377 | defsubr (&Slist); | 7377 | defsubr (&Slist); |
diff --git a/src/bignum.c b/src/bignum.c index 009d73118c2..3883d3a3944 100644 --- a/src/bignum.c +++ b/src/bignum.c | |||
| @@ -82,8 +82,11 @@ static Lisp_Object | |||
| 82 | make_bignum_bits (size_t bits) | 82 | make_bignum_bits (size_t bits) |
| 83 | { | 83 | { |
| 84 | /* The documentation says integer-width should be nonnegative, so | 84 | /* The documentation says integer-width should be nonnegative, so |
| 85 | a single comparison suffices even though 'bits' is unsigned. */ | 85 | comparing it to BITS works even though BITS is unsigned. Treat |
| 86 | if (integer_width < bits) | 86 | integer-width as if it were at least twice the machine integer width, |
| 87 | so that timefns.c can safely use bignums for double-precision | ||
| 88 | timestamps. */ | ||
| 89 | if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits) | ||
| 87 | overflow_error (); | 90 | overflow_error (); |
| 88 | 91 | ||
| 89 | struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum, | 92 | struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum, |