aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-01-10 21:35:31 -0800
committerPaul Eggert2019-01-10 21:39:56 -0800
commit470082de55f7b1c1cde8aabbb5b8de55b4b08f83 (patch)
tree73f67a8951cdeb998a822fd38a6abd242b16199a /src
parent9609db9d98babfe8782a03aebe46176e57905c63 (diff)
downloademacs-470082de55f7b1c1cde8aabbb5b8de55b4b08f83.tar.gz
emacs-470082de55f7b1c1cde8aabbb5b8de55b4b08f83.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c13
-rw-r--r--src/fns.c11
2 files changed, 16 insertions, 8 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 407ac725414..31e8da70161 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2774,6 +2774,19 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2774 { 2774 {
2775 if (cons_block_index == CONS_BLOCK_SIZE) 2775 if (cons_block_index == CONS_BLOCK_SIZE)
2776 { 2776 {
2777 /* Maximum number of conses that should be active at any
2778 given time, so that list lengths fit into a ptrdiff_t and
2779 into a fixnum. */
2780 ptrdiff_t max_conses = min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM);
2781
2782 /* This check is typically optimized away, as a runtime
2783 check is needed only on weird platforms where a count of
2784 distinct conses might not fit. */
2785 if (max_conses < INTPTR_MAX / sizeof (struct Lisp_Cons)
2786 && (max_conses - CONS_BLOCK_SIZE
2787 < total_free_conses + total_conses))
2788 memory_full (sizeof (struct cons_block));
2789
2777 struct cons_block *new 2790 struct cons_block *new
2778 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); 2791 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2779 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2792 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
diff --git a/src/fns.c b/src/fns.c
index 0fad6f47447..6fcb38e4b04 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -101,9 +101,7 @@ list_length (Lisp_Object list)
101 FOR_EACH_TAIL (list) 101 FOR_EACH_TAIL (list)
102 i++; 102 i++;
103 CHECK_LIST_END (list, list); 103 CHECK_LIST_END (list, list);
104 if (i <= min (PTRDIFF_MAX, MOST_POSITIVE_FIXNUM)) 104 return i;
105 return i;
106 overflow_error ();
107} 105}
108 106
109 107
@@ -141,14 +139,13 @@ DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
141 doc: /* Return the length of a list, but avoid error or infinite loop. 139 doc: /* Return the length of a list, but avoid error or infinite loop.
142This function never gets an error. If LIST is not really a list, 140This function never gets an error. If LIST is not really a list,
143it returns 0. If LIST is circular, it returns an integer that is at 141it returns 0. If LIST is circular, it returns an integer that is at
144least the number of distinct elements. 142least the number of distinct elements. */)
145Value is a fixnum, if it's small enough, otherwise a bignum. */)
146 (Lisp_Object list) 143 (Lisp_Object list)
147{ 144{
148 intptr_t len = 0; 145 intptr_t len = 0;
149 FOR_EACH_TAIL_SAFE (list) 146 FOR_EACH_TAIL_SAFE (list)
150 len++; 147 len++;
151 return INT_TO_INTEGER (len); 148 return make_fixnum (len);
152} 149}
153 150
154DEFUN ("proper-list-p", Fproper_list_p, Sproper_list_p, 1, 1, 0, 151DEFUN ("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). */
168 } 165 }
169 if (!NILP (last_tail)) 166 if (!NILP (last_tail))
170 return Qnil; 167 return Qnil;
171 if (MOST_POSITIVE_FIXNUM < len)
172 overflow_error ();
173 return make_fixnum (len); 168 return make_fixnum (len);
174} 169}
175 170