aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-03-29 10:16:29 -0700
committerPaul Eggert2018-03-29 11:03:07 -0700
commit6b3d01dad415230ad0bd0d01a05351d7a8b0e8c3 (patch)
treed49bf4520d6afc830aa9d016be3d57349b251c4f /src
parent3409fe0362c52127c52f854a7300f4dde4b8fffe (diff)
downloademacs-6b3d01dad415230ad0bd0d01a05351d7a8b0e8c3.tar.gz
emacs-6b3d01dad415230ad0bd0d01a05351d7a8b0e8c3.zip
Lisp reader now checks for integer overflow
* doc/lispref/numbers.texi (Integer Basics), etc/NEWS: Document this. * src/lisp.h (S2N_IGNORE_TRAILING, S2N_OVERFLOW_TO_FLOAT): New constants. * src/lread.c (string_to_number): Change trailing bool arg to integer argument with flags, to support S2N_OVERFLOW_TO_FLOAT. All uses changed. * test/src/editfns-tests.el (read-large-integer): New test.
Diffstat (limited to 'src')
-rw-r--r--src/data.c9
-rw-r--r--src/lisp.h3
-rw-r--r--src/lread.c35
-rw-r--r--src/process.c2
4 files changed, 27 insertions, 22 deletions
diff --git a/src/data.c b/src/data.c
index a7fab1ef58a..6f23a26757a 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2716,9 +2716,7 @@ present, base 10 is used. BASE must be between 2 and 16 (inclusive).
2716If the base used is not 10, STRING is always parsed as an integer. */) 2716If the base used is not 10, STRING is always parsed as an integer. */)
2717 (register Lisp_Object string, Lisp_Object base) 2717 (register Lisp_Object string, Lisp_Object base)
2718{ 2718{
2719 register char *p; 2719 int b;
2720 register int b;
2721 Lisp_Object val;
2722 2720
2723 CHECK_STRING (string); 2721 CHECK_STRING (string);
2724 2722
@@ -2732,11 +2730,12 @@ If the base used is not 10, STRING is always parsed as an integer. */)
2732 b = XINT (base); 2730 b = XINT (base);
2733 } 2731 }
2734 2732
2735 p = SSDATA (string); 2733 char *p = SSDATA (string);
2736 while (*p == ' ' || *p == '\t') 2734 while (*p == ' ' || *p == '\t')
2737 p++; 2735 p++;
2738 2736
2739 val = string_to_number (p, b, true); 2737 int flags = S2N_IGNORE_TRAILING | S2N_OVERFLOW_TO_FLOAT;
2738 Lisp_Object val = string_to_number (p, b, flags);
2740 return NILP (val) ? make_number (0) : val; 2739 return NILP (val) ? make_number (0) : val;
2741} 2740}
2742 2741
diff --git a/src/lisp.h b/src/lisp.h
index f0c0c5a14a5..b931d23bf38 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3899,7 +3899,8 @@ LOADHIST_ATTACH (Lisp_Object x)
3899} 3899}
3900extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, 3900extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
3901 Lisp_Object *, Lisp_Object, bool); 3901 Lisp_Object *, Lisp_Object, bool);
3902extern Lisp_Object string_to_number (char const *, int, bool); 3902enum { S2N_IGNORE_TRAILING = 1, S2N_OVERFLOW_TO_FLOAT = 2 };
3903extern Lisp_Object string_to_number (char const *, int, int);
3903extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), 3904extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
3904 Lisp_Object); 3905 Lisp_Object);
3905extern void dir_warning (const char *, Lisp_Object); 3906extern void dir_warning (const char *, Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index 381f9cf20c5..a774524ee43 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2339,7 +2339,7 @@ character_name_to_code (char const *name, ptrdiff_t name_len)
2339 monstrosities like "U+-0000". */ 2339 monstrosities like "U+-0000". */
2340 Lisp_Object code 2340 Lisp_Object code
2341 = (name[0] == 'U' && name[1] == '+' 2341 = (name[0] == 'U' && name[1] == '+'
2342 ? string_to_number (name + 1, 16, false) 2342 ? string_to_number (name + 1, 16, 0)
2343 : call2 (Qchar_from_name, make_unibyte_string (name, name_len), Qt)); 2343 : call2 (Qchar_from_name, make_unibyte_string (name, name_len), Qt));
2344 2344
2345 if (! RANGED_INTEGERP (0, code, MAX_UNICODE_CHAR) 2345 if (! RANGED_INTEGERP (0, code, MAX_UNICODE_CHAR)
@@ -2693,7 +2693,7 @@ read_integer (Lisp_Object readcharfun, EMACS_INT radix)
2693 invalid_syntax (buf); 2693 invalid_syntax (buf);
2694 } 2694 }
2695 2695
2696 return string_to_number (buf, radix, false); 2696 return string_to_number (buf, radix, 0);
2697} 2697}
2698 2698
2699 2699
@@ -3502,7 +3502,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3502 3502
3503 if (!quoted && !uninterned_symbol) 3503 if (!quoted && !uninterned_symbol)
3504 { 3504 {
3505 Lisp_Object result = string_to_number (read_buffer, 10, false); 3505 Lisp_Object result = string_to_number (read_buffer, 10, 0);
3506 if (! NILP (result)) 3506 if (! NILP (result))
3507 return unbind_to (count, result); 3507 return unbind_to (count, result);
3508 } 3508 }
@@ -3667,16 +3667,17 @@ substitute_in_interval (INTERVAL interval, void *arg)
3667} 3667}
3668 3668
3669 3669
3670/* Convert STRING to a number, assuming base BASE. Return a fixnum if 3670/* Convert STRING to a number, assuming base BASE. When STRING has
3671 STRING has integer syntax and fits in a fixnum, else return the 3671 floating point syntax and BASE is 10, return a nearest float. When
3672 nearest float if STRING has either floating point or integer syntax 3672 STRING has integer syntax, return a fixnum if the integer fits, and
3673 and BASE is 10, else return nil. If IGNORE_TRAILING, consider just 3673 signal an overflow otherwise (unless BASE is 10 and STRING ends in
3674 the longest prefix of STRING that has valid floating point syntax. 3674 period or FLAGS & S2N_OVERFLOW_TO_FLOAT is nonzero; in this case,
3675 Signal an overflow if BASE is not 10 and the number has integer 3675 return a nearest float instead). Otherwise, return nil. If FLAGS
3676 syntax but does not fit. */ 3676 & S2N_IGNORE_TRAILING is nonzero, consider just the longest prefix
3677 of STRING that has valid syntax. */
3677 3678
3678Lisp_Object 3679Lisp_Object
3679string_to_number (char const *string, int base, bool ignore_trailing) 3680string_to_number (char const *string, int base, int flags)
3680{ 3681{
3681 char const *cp = string; 3682 char const *cp = string;
3682 bool float_syntax = 0; 3683 bool float_syntax = 0;
@@ -3759,9 +3760,10 @@ string_to_number (char const *string, int base, bool ignore_trailing)
3759 || (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP)); 3760 || (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP));
3760 } 3761 }
3761 3762
3762 /* Return nil if the number uses invalid syntax. If IGNORE_TRAILING, accept 3763 /* Return nil if the number uses invalid syntax. If FLAGS &
3763 any prefix that matches. Otherwise, the entire string must match. */ 3764 S2N_IGNORE_TRAILING, accept any prefix that matches. Otherwise,
3764 if (! (ignore_trailing 3765 the entire string must match. */
3766 if (! (flags & S2N_IGNORE_TRAILING
3765 ? ((state & LEAD_INT) != 0 || float_syntax) 3767 ? ((state & LEAD_INT) != 0 || float_syntax)
3766 : (!*cp && ((state & ~(INTOVERFLOW | DOT_CHAR)) == LEAD_INT 3768 : (!*cp && ((state & ~(INTOVERFLOW | DOT_CHAR)) == LEAD_INT
3767 || float_syntax)))) 3769 || float_syntax))))
@@ -3776,7 +3778,7 @@ string_to_number (char const *string, int base, bool ignore_trailing)
3776 /* Unfortunately there's no simple and accurate way to convert 3778 /* Unfortunately there's no simple and accurate way to convert
3777 non-base-10 numbers that are out of C-language range. */ 3779 non-base-10 numbers that are out of C-language range. */
3778 if (base != 10) 3780 if (base != 10)
3779 xsignal1 (Qoverflow_error, build_string (string)); 3781 flags = 0;
3780 } 3782 }
3781 else if (n <= (negative ? -MOST_NEGATIVE_FIXNUM : MOST_POSITIVE_FIXNUM)) 3783 else if (n <= (negative ? -MOST_NEGATIVE_FIXNUM : MOST_POSITIVE_FIXNUM))
3782 { 3784 {
@@ -3785,6 +3787,9 @@ string_to_number (char const *string, int base, bool ignore_trailing)
3785 } 3787 }
3786 else 3788 else
3787 value = n; 3789 value = n;
3790
3791 if (! (state & DOT_CHAR) && ! (flags & S2N_OVERFLOW_TO_FLOAT))
3792 xsignal1 (Qoverflow_error, build_string (string));
3788 } 3793 }
3789 3794
3790 /* Either the number uses float syntax, or it does not fit into a fixnum. 3795 /* Either the number uses float syntax, or it does not fit into a fixnum.
diff --git a/src/process.c b/src/process.c
index 2aaa238f60c..ed2cab7b51f 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6842,7 +6842,7 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */)
6842 { 6842 {
6843 Lisp_Object tem = Fget_process (process); 6843 Lisp_Object tem = Fget_process (process);
6844 if (NILP (tem)) 6844 if (NILP (tem))
6845 tem = string_to_number (SSDATA (process), 10, true); 6845 tem = string_to_number (SSDATA (process), 10, S2N_OVERFLOW_TO_FLOAT);
6846 process = tem; 6846 process = tem;
6847 } 6847 }
6848 else if (!NUMBERP (process)) 6848 else if (!NUMBERP (process))