From: Paul Eggert Date: Tue, 4 Jun 2019 15:13:20 +0000 (-0700) Subject: Always allow at least double-precision bignums X-Git-Tag: emacs-27.0.90~2702 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=7f4558e3d9edbdee6901e5fbcd4a4072f49ec5b9;p=emacs.git 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. --- diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index fbdd83fa86e..cae8babcb40 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -191,19 +191,19 @@ on 64-bit platforms. @cindex integer range @cindex number of bignum bits, limit on @defvar integer-width -The value of this variable is a nonnegative integer that is an upper -bound on the number of bits in a bignum. Integers outside the fixnum -range are limited to absolute values less than +The value of this variable is a nonnegative integer that controls +whether Emacs signals a range error when a large integer would be +calculated. Integers with absolute values less than @ifnottex 2**@var{n}, @end ifnottex @tex @math{2^{n}}, @end tex -where @var{n} is this variable's value. Attempts to create bignums outside -this range signal a range error. Setting this variable -to zero disables creation of bignums; setting it to a large number can -cause Emacs to consume large quantities of memory if a computation +where @var{n} is this variable's value, do not signal a range error. +Attempts to create larger integers typically signal a range error, +although there might be no signal if a larger integer can be created cheaply. +Setting this variable to a large number can be costly if a computation creates huge integers. @end defvar 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. */); doc: /* Accumulated number of garbage collections done. */); DEFVAR_INT ("integer-width", integer_width, - doc: /* Maximum number of bits in bignums. -Integers outside the fixnum range are limited to absolute values less -than 2**N, where N is this variable's value. N should be nonnegative. */); + doc: /* Maximum number N of bits in safely-calculated integers. +Integers with absolute values less than 2**N do not signal a range error. +N should be nonnegative. */); defsubr (&Scons); 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 make_bignum_bits (size_t bits) { /* The documentation says integer-width should be nonnegative, so - a single comparison suffices even though 'bits' is unsigned. */ - if (integer_width < bits) + comparing it to BITS works even though BITS is unsigned. Treat + integer-width as if it were at least twice the machine integer width, + so that timefns.c can safely use bignums for double-precision + timestamps. */ + if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits) overflow_error (); struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum,