From: Paul Eggert Date: Thu, 23 Jun 2011 00:55:55 +0000 (-0700) Subject: * lread.c: Integer overflow fixes. X-Git-Tag: emacs-pretest-24.0.90~104^2~152^2~436 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8b9ac8b4a241b0f3be53e6438e69b227aac20d24;p=emacs.git * lread.c: Integer overflow fixes. (read_integer): Radix is now EMACS_INT, not int, to improve quality of diagnostics for out-of-range radices. Calculate buffer size correctly for out-of-range radices. (read1): Check for integer overflow in radices, and in read-circle numbers. --- diff --git a/src/ChangeLog b/src/ChangeLog index 7f174bf0a21..96e6741f11f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,12 @@ 2011-06-23 Paul Eggert + * lread.c: Integer overflow fixes. + (read_integer): Radix is now EMACS_INT, not int, + to improve quality of diagnostics for out-of-range radices. + Calculate buffer size correctly for out-of-range radices. + (read1): Check for integer overflow in radices, and in + read-circle numbers. + * image.c (cache_image): Check for size arithmetic overflow. 2011-06-22 Paul Eggert diff --git a/src/lread.c b/src/lread.c index a2f78f848ae..2f1c05c5aa1 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2277,10 +2277,12 @@ digit_to_number (int character, int base) range. */ static Lisp_Object -read_integer (Lisp_Object readcharfun, int radix) +read_integer (Lisp_Object readcharfun, EMACS_INT radix) { - /* Room for sign, leading 0, other digits, trailing null byte. */ - char buf[1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1]; + /* Room for sign, leading 0, other digits, trailing null byte. + Also, room for invalid syntax diagnostic. */ + char buf[max (1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1, + sizeof "integer, radix " + INT_STRLEN_BOUND (EMACS_INT))]; int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */ @@ -2332,7 +2334,7 @@ read_integer (Lisp_Object readcharfun, int radix) if (! valid) { - sprintf (buf, "integer, radix %d", radix); + sprintf (buf, "integer, radix %"pI"d", radix); invalid_syntax (buf); } @@ -2663,49 +2665,60 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) /* Reader forms that can reuse previously read objects. */ if (c >= '0' && c <= '9') { - int n = 0; + EMACS_INT n = 0; Lisp_Object tem; /* Read a non-negative integer. */ while (c >= '0' && c <= '9') { - n *= 10; - n += c - '0'; + if (MOST_POSITIVE_FIXNUM / 10 < n + || MOST_POSITIVE_FIXNUM < n * 10 + c - '0') + n = MOST_POSITIVE_FIXNUM + 1; + else + n = n * 10 + c - '0'; c = READCHAR; } - /* #n=object returns object, but associates it with n for #n#. */ - if (c == '=' && !NILP (Vread_circle)) + + if (n <= MOST_POSITIVE_FIXNUM) { - /* Make a placeholder for #n# to use temporarily */ - Lisp_Object placeholder; - Lisp_Object cell; + if (c == 'r' || c == 'R') + return read_integer (readcharfun, n); - placeholder = Fcons (Qnil, Qnil); - cell = Fcons (make_number (n), placeholder); - read_objects = Fcons (cell, read_objects); + if (! NILP (Vread_circle)) + { + /* #n=object returns object, but associates it with + n for #n#. */ + if (c == '=') + { + /* Make a placeholder for #n# to use temporarily */ + Lisp_Object placeholder; + Lisp_Object cell; - /* Read the object itself. */ - tem = read0 (readcharfun); + placeholder = Fcons (Qnil, Qnil); + cell = Fcons (make_number (n), placeholder); + read_objects = Fcons (cell, read_objects); - /* Now put it everywhere the placeholder was... */ - substitute_object_in_subtree (tem, placeholder); + /* Read the object itself. */ + tem = read0 (readcharfun); - /* ...and #n# will use the real value from now on. */ - Fsetcdr (cell, tem); + /* Now put it everywhere the placeholder was... */ + substitute_object_in_subtree (tem, placeholder); - return tem; - } - /* #n# returns a previously read object. */ - if (c == '#' && !NILP (Vread_circle)) - { - tem = Fassq (make_number (n), read_objects); - if (CONSP (tem)) - return XCDR (tem); - /* Fall through to error message. */ - } - else if (c == 'r' || c == 'R') - return read_integer (readcharfun, n); + /* ...and #n# will use the real value from now on. */ + Fsetcdr (cell, tem); + return tem; + } + + /* #n# returns a previously read object. */ + if (c == '#') + { + tem = Fassq (make_number (n), read_objects); + if (CONSP (tem)) + return XCDR (tem); + } + } + } /* Fall through to error message. */ } else if (c == 'x' || c == 'X')