* fns.c (Flength): Don't overflow int when computing a list length.
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 14 Jun 2011 22:01:32 +0000 (15:01 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 14 Jun 2011 22:01:32 +0000 (15:01 -0700)
Use EMACS_INT, not int, to avoid unwanted truncation on 64-bit hosts.
Check for QUIT every 1024 entries rather than every other entry;
that's faster and is responsive enough.  Report an error instead of
overflowing an integer.

src/ChangeLog
src/fns.c

index dd61843..5d70c56 100644 (file)
@@ -1,5 +1,11 @@
 2011-06-14  Paul Eggert  <eggert@cs.ucla.edu>
 
+       * fns.c (Flength): Don't overflow int when computing a list length.
+       Use EMACS_INT, not int, to avoid unwanted truncation on 64-bit hosts.
+       Check for QUIT every 1024 entries rather than every other entry;
+       that's faster and is responsive enough.  Report an error instead of
+       overflowing an integer.
+
        * alloc.c: Check that resized vectors' lengths fit in fixnums.
        (header_size, word_size): New constants.
        (allocate_vectorlike): Don't check size overflow here.
index 333a75a..7d5d1bd 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -110,7 +110,6 @@ To get the number of bytes, use `string-bytes'.  */)
   (register Lisp_Object sequence)
 {
   register Lisp_Object val;
-  register int i;
 
   if (STRINGP (sequence))
     XSETFASTINT (val, SCHARS (sequence));
@@ -124,19 +123,20 @@ To get the number of bytes, use `string-bytes'.  */)
     XSETFASTINT (val, ASIZE (sequence) & PSEUDOVECTOR_SIZE_MASK);
   else if (CONSP (sequence))
     {
-      i = 0;
-      while (CONSP (sequence))
+      EMACS_INT i = 0;
+
+      do
        {
-         sequence = XCDR (sequence);
          ++i;
-
-         if (!CONSP (sequence))
-           break;
-
+         if ((i & ((1 << 10) - 1)) == 0)
+           {
+             if (MOST_POSITIVE_FIXNUM < i)
+               error ("List too long");
+             QUIT;
+           }
          sequence = XCDR (sequence);
-         ++i;
-         QUIT;
        }
+      while (CONSP (sequence));
 
       CHECK_LIST_END (sequence, sequence);