[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 470082d: List lengths are always fixnums now
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] master 470082d: List lengths are always fixnums now |
Date: |
Fri, 11 Jan 2019 00:40:01 -0500 (EST) |
branch: master
commit 470082de55f7b1c1cde8aabbb5b8de55b4b08f83
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>
List lengths are always fixnums now
Without this patch, it was theoretically possible for a list
length to be a bignum, which means that safe-length could
signal an error (due to generating a too-large bignum) contrary
to its documentation. Fix things to remove the theoretical
possibility, so that list lengths are always fixnums (and so
that list lenghts are always ptrdiff_t values too, since that
is assumed internally anyway).
* src/alloc.c (Fcons): Do not allocate so many conses that
a list length won’t fit into ptrdiff_t or into fixnum.
This matters only on weird platforms; on typical platforms,
list lengths always fit anyway.
* src/fns.c (list_length, Fsafe_length, proper-list-p):
Remove integer overflow checks that are no longer needed.
---
src/alloc.c | 13 +++++++++++++
src/fns.c | 11 +++--------
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/src/alloc.c b/src/alloc.c
index 407ac72..31e8da7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2774,6 +2774,19 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
{
if (cons_block_index == CONS_BLOCK_SIZE)
{
+ /* Maximum number of conses that should be active at any
+ given time, so that list lengths fit into a ptrdiff_t and
+ into a fixnum. */
+ ptrdiff_t max_conses = min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM);
+
+ /* This check is typically optimized away, as a runtime
+ check is needed only on weird platforms where a count of
+ distinct conses might not fit. */
+ if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons)
+ && (max_conses - CONS_BLOCK_SIZE
+ < total_free_conses + total_conses))
+ memory_full (sizeof (struct cons_block));
+
struct cons_block *new
= lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
diff --git a/src/fns.c b/src/fns.c
index 0fad6f4..6fcb38e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -101,9 +101,7 @@ list_length (Lisp_Object list)
FOR_EACH_TAIL (list)
i++;
CHECK_LIST_END (list, list);
- if (i <= min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM))
- return i;
- overflow_error ();
+ return i;
}
@@ -141,14 +139,13 @@ DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
doc: /* Return the length of a list, but avoid error or infinite loop.
This function never gets an error. If LIST is not really a list,
it returns 0. If LIST is circular, it returns an integer that is at
-least the number of distinct elements.
-Value is a fixnum, if it's small enough, otherwise a bignum. */)
+least the number of distinct elements. */)
(Lisp_Object list)
{
intptr_t len = 0;
FOR_EACH_TAIL_SAFE (list)
len++;
- return INT_TO_INTEGER (len);
+ return make_fixnum (len);
}
DEFUN ("proper-list-p", Fproper_list_p, Sproper_list_p, 1, 1, 0,
@@ -168,8 +165,6 @@ A proper list is neither circular nor dotted (i.e., its
last cdr is nil). */
}
if (!NILP (last_tail))
return Qnil;
- if (MOST_POSITIVE_FIXNUM < len)
- overflow_error ();
return make_fixnum (len);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master 470082d: List lengths are always fixnums now,
Paul Eggert <=