diff options
| author | Paul Eggert | 2011-06-22 17:55:55 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-06-22 17:55:55 -0700 |
| commit | 8b9ac8b4a241b0f3be53e6438e69b227aac20d24 (patch) | |
| tree | 54a83c4d055dad72e8521ce1cf4710c552418042 /src | |
| parent | 7fcccf1efe3d4bc6182253ec0b1b5fd409fdd242 (diff) | |
| download | emacs-8b9ac8b4a241b0f3be53e6438e69b227aac20d24.tar.gz emacs-8b9ac8b4a241b0f3be53e6438e69b227aac20d24.zip | |
* 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 7 | ||||
| -rw-r--r-- | src/lread.c | 79 |
2 files changed, 53 insertions, 33 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 7f174bf0a21..96e6741f11f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,12 @@ | |||
| 1 | 2011-06-23 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-06-23 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | * lread.c: Integer overflow fixes. | ||
| 4 | (read_integer): Radix is now EMACS_INT, not int, | ||
| 5 | to improve quality of diagnostics for out-of-range radices. | ||
| 6 | Calculate buffer size correctly for out-of-range radices. | ||
| 7 | (read1): Check for integer overflow in radices, and in | ||
| 8 | read-circle numbers. | ||
| 9 | |||
| 3 | * image.c (cache_image): Check for size arithmetic overflow. | 10 | * image.c (cache_image): Check for size arithmetic overflow. |
| 4 | 11 | ||
| 5 | 2011-06-22 Paul Eggert <eggert@cs.ucla.edu> | 12 | 2011-06-22 Paul Eggert <eggert@cs.ucla.edu> |
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) | |||
| 2277 | range. */ | 2277 | range. */ |
| 2278 | 2278 | ||
| 2279 | static Lisp_Object | 2279 | static Lisp_Object |
| 2280 | read_integer (Lisp_Object readcharfun, int radix) | 2280 | read_integer (Lisp_Object readcharfun, EMACS_INT radix) |
| 2281 | { | 2281 | { |
| 2282 | /* Room for sign, leading 0, other digits, trailing null byte. */ | 2282 | /* Room for sign, leading 0, other digits, trailing null byte. |
| 2283 | char buf[1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1]; | 2283 | Also, room for invalid syntax diagnostic. */ |
| 2284 | char buf[max (1 + 1 + sizeof (uintmax_t) * CHAR_BIT + 1, | ||
| 2285 | sizeof "integer, radix " + INT_STRLEN_BOUND (EMACS_INT))]; | ||
| 2284 | 2286 | ||
| 2285 | int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */ | 2287 | int valid = -1; /* 1 if valid, 0 if not, -1 if incomplete. */ |
| 2286 | 2288 | ||
| @@ -2332,7 +2334,7 @@ read_integer (Lisp_Object readcharfun, int radix) | |||
| 2332 | 2334 | ||
| 2333 | if (! valid) | 2335 | if (! valid) |
| 2334 | { | 2336 | { |
| 2335 | sprintf (buf, "integer, radix %d", radix); | 2337 | sprintf (buf, "integer, radix %"pI"d", radix); |
| 2336 | invalid_syntax (buf); | 2338 | invalid_syntax (buf); |
| 2337 | } | 2339 | } |
| 2338 | 2340 | ||
| @@ -2663,49 +2665,60 @@ read1 (register Lisp_Object readcharfun, int *pch, int first_in_list) | |||
| 2663 | /* Reader forms that can reuse previously read objects. */ | 2665 | /* Reader forms that can reuse previously read objects. */ |
| 2664 | if (c >= '0' && c <= '9') | 2666 | if (c >= '0' && c <= '9') |
| 2665 | { | 2667 | { |
| 2666 | int n = 0; | 2668 | EMACS_INT n = 0; |
| 2667 | Lisp_Object tem; | 2669 | Lisp_Object tem; |
| 2668 | 2670 | ||
| 2669 | /* Read a non-negative integer. */ | 2671 | /* Read a non-negative integer. */ |
| 2670 | while (c >= '0' && c <= '9') | 2672 | while (c >= '0' && c <= '9') |
| 2671 | { | 2673 | { |
| 2672 | n *= 10; | 2674 | if (MOST_POSITIVE_FIXNUM / 10 < n |
| 2673 | n += c - '0'; | 2675 | || MOST_POSITIVE_FIXNUM < n * 10 + c - '0') |
| 2676 | n = MOST_POSITIVE_FIXNUM + 1; | ||
| 2677 | else | ||
| 2678 | n = n * 10 + c - '0'; | ||
| 2674 | c = READCHAR; | 2679 | c = READCHAR; |
| 2675 | } | 2680 | } |
| 2676 | /* #n=object returns object, but associates it with n for #n#. */ | 2681 | |
| 2677 | if (c == '=' && !NILP (Vread_circle)) | 2682 | if (n <= MOST_POSITIVE_FIXNUM) |
| 2678 | { | 2683 | { |
| 2679 | /* Make a placeholder for #n# to use temporarily */ | 2684 | if (c == 'r' || c == 'R') |
| 2680 | Lisp_Object placeholder; | 2685 | return read_integer (readcharfun, n); |
| 2681 | Lisp_Object cell; | ||
| 2682 | 2686 | ||
| 2683 | placeholder = Fcons (Qnil, Qnil); | 2687 | if (! NILP (Vread_circle)) |
| 2684 | cell = Fcons (make_number (n), placeholder); | 2688 | { |
| 2685 | read_objects = Fcons (cell, read_objects); | 2689 | /* #n=object returns object, but associates it with |
| 2690 | n for #n#. */ | ||
| 2691 | if (c == '=') | ||
| 2692 | { | ||
| 2693 | /* Make a placeholder for #n# to use temporarily */ | ||
| 2694 | Lisp_Object placeholder; | ||
| 2695 | Lisp_Object cell; | ||
| 2686 | 2696 | ||
| 2687 | /* Read the object itself. */ | 2697 | placeholder = Fcons (Qnil, Qnil); |
| 2688 | tem = read0 (readcharfun); | 2698 | cell = Fcons (make_number (n), placeholder); |
| 2699 | read_objects = Fcons (cell, read_objects); | ||
| 2689 | 2700 | ||
| 2690 | /* Now put it everywhere the placeholder was... */ | 2701 | /* Read the object itself. */ |
| 2691 | substitute_object_in_subtree (tem, placeholder); | 2702 | tem = read0 (readcharfun); |
| 2692 | 2703 | ||
| 2693 | /* ...and #n# will use the real value from now on. */ | 2704 | /* Now put it everywhere the placeholder was... */ |
| 2694 | Fsetcdr (cell, tem); | 2705 | substitute_object_in_subtree (tem, placeholder); |
| 2695 | 2706 | ||
| 2696 | return tem; | 2707 | /* ...and #n# will use the real value from now on. */ |
| 2697 | } | 2708 | Fsetcdr (cell, tem); |
| 2698 | /* #n# returns a previously read object. */ | ||
| 2699 | if (c == '#' && !NILP (Vread_circle)) | ||
| 2700 | { | ||
| 2701 | tem = Fassq (make_number (n), read_objects); | ||
| 2702 | if (CONSP (tem)) | ||
| 2703 | return XCDR (tem); | ||
| 2704 | /* Fall through to error message. */ | ||
| 2705 | } | ||
| 2706 | else if (c == 'r' || c == 'R') | ||
| 2707 | return read_integer (readcharfun, n); | ||
| 2708 | 2709 | ||
| 2710 | return tem; | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | /* #n# returns a previously read object. */ | ||
| 2714 | if (c == '#') | ||
| 2715 | { | ||
| 2716 | tem = Fassq (make_number (n), read_objects); | ||
| 2717 | if (CONSP (tem)) | ||
| 2718 | return XCDR (tem); | ||
| 2719 | } | ||
| 2720 | } | ||
| 2721 | } | ||
| 2709 | /* Fall through to error message. */ | 2722 | /* Fall through to error message. */ |
| 2710 | } | 2723 | } |
| 2711 | else if (c == 'x' || c == 'X') | 2724 | else if (c == 'x' || c == 'X') |