diff options
| author | Paul Eggert | 2011-05-27 12:37:32 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-05-27 12:37:32 -0700 |
| commit | 0f6990a78ae5016d8ae73253cdb4739adf0197e7 (patch) | |
| tree | 78c7860e14d7cf6bc73526174493a02e606dfc13 /src/data.c | |
| parent | fb1ac845caea7da6ba98b93c3d67fa67c651b8ef (diff) | |
| parent | b57f7e0a357aacf98ec5be826f7227f37e9806b8 (diff) | |
| download | emacs-0f6990a78ae5016d8ae73253cdb4739adf0197e7.tar.gz emacs-0f6990a78ae5016d8ae73253cdb4739adf0197e7.zip | |
Merge: Integer overflow fixes.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/src/data.c b/src/data.c index 577ae777d89..ce0e8e40f51 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -22,6 +22,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 22 | #include <signal.h> | 22 | #include <signal.h> |
| 23 | #include <stdio.h> | 23 | #include <stdio.h> |
| 24 | #include <setjmp.h> | 24 | #include <setjmp.h> |
| 25 | |||
| 26 | #include <intprops.h> | ||
| 27 | |||
| 25 | #include "lisp.h" | 28 | #include "lisp.h" |
| 26 | #include "puresize.h" | 29 | #include "puresize.h" |
| 27 | #include "character.h" | 30 | #include "character.h" |
| @@ -2431,6 +2434,10 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | |||
| 2431 | register EMACS_INT accum = 0; | 2434 | register EMACS_INT accum = 0; |
| 2432 | register EMACS_INT next; | 2435 | register EMACS_INT next; |
| 2433 | 2436 | ||
| 2437 | int overflow = 0; | ||
| 2438 | size_t ok_args; | ||
| 2439 | EMACS_INT ok_accum; | ||
| 2440 | |||
| 2434 | switch (SWITCH_ENUM_CAST (code)) | 2441 | switch (SWITCH_ENUM_CAST (code)) |
| 2435 | { | 2442 | { |
| 2436 | case Alogior: | 2443 | case Alogior: |
| @@ -2451,25 +2458,48 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | |||
| 2451 | 2458 | ||
| 2452 | for (argnum = 0; argnum < nargs; argnum++) | 2459 | for (argnum = 0; argnum < nargs; argnum++) |
| 2453 | { | 2460 | { |
| 2461 | if (! overflow) | ||
| 2462 | { | ||
| 2463 | ok_args = argnum; | ||
| 2464 | ok_accum = accum; | ||
| 2465 | } | ||
| 2466 | |||
| 2454 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ | 2467 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ |
| 2455 | val = args[argnum]; | 2468 | val = args[argnum]; |
| 2456 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); | 2469 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); |
| 2457 | 2470 | ||
| 2458 | if (FLOATP (val)) | 2471 | if (FLOATP (val)) |
| 2459 | return float_arith_driver ((double) accum, argnum, code, | 2472 | return float_arith_driver (ok_accum, ok_args, code, |
| 2460 | nargs, args); | 2473 | nargs, args); |
| 2461 | args[argnum] = val; | 2474 | args[argnum] = val; |
| 2462 | next = XINT (args[argnum]); | 2475 | next = XINT (args[argnum]); |
| 2463 | switch (SWITCH_ENUM_CAST (code)) | 2476 | switch (SWITCH_ENUM_CAST (code)) |
| 2464 | { | 2477 | { |
| 2465 | case Aadd: | 2478 | case Aadd: |
| 2479 | if (INT_ADD_OVERFLOW (accum, next)) | ||
| 2480 | { | ||
| 2481 | overflow = 1; | ||
| 2482 | accum &= INTMASK; | ||
| 2483 | } | ||
| 2466 | accum += next; | 2484 | accum += next; |
| 2467 | break; | 2485 | break; |
| 2468 | case Asub: | 2486 | case Asub: |
| 2487 | if (INT_SUBTRACT_OVERFLOW (accum, next)) | ||
| 2488 | { | ||
| 2489 | overflow = 1; | ||
| 2490 | accum &= INTMASK; | ||
| 2491 | } | ||
| 2469 | accum = argnum ? accum - next : nargs == 1 ? - next : next; | 2492 | accum = argnum ? accum - next : nargs == 1 ? - next : next; |
| 2470 | break; | 2493 | break; |
| 2471 | case Amult: | 2494 | case Amult: |
| 2472 | accum *= next; | 2495 | if (INT_MULTIPLY_OVERFLOW (accum, next)) |
| 2496 | { | ||
| 2497 | EMACS_UINT a = accum, b = next, ab = a * b; | ||
| 2498 | overflow = 1; | ||
| 2499 | accum = ab & INTMASK; | ||
| 2500 | } | ||
| 2501 | else | ||
| 2502 | accum *= next; | ||
| 2473 | break; | 2503 | break; |
| 2474 | case Adiv: | 2504 | case Adiv: |
| 2475 | if (!argnum) | 2505 | if (!argnum) |
| @@ -2501,6 +2531,9 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | |||
| 2501 | } | 2531 | } |
| 2502 | } | 2532 | } |
| 2503 | 2533 | ||
| 2534 | accum &= INTMASK; | ||
| 2535 | if (MOST_POSITIVE_FIXNUM < accum) | ||
| 2536 | accum += MOST_NEGATIVE_FIXNUM - (MOST_POSITIVE_FIXNUM + 1); | ||
| 2504 | XSETINT (val, accum); | 2537 | XSETINT (val, accum); |
| 2505 | return val; | 2538 | return val; |
| 2506 | } | 2539 | } |
| @@ -2760,11 +2793,11 @@ In this case, zeros are shifted in on the left. */) | |||
| 2760 | if (XINT (count) >= BITS_PER_EMACS_INT) | 2793 | if (XINT (count) >= BITS_PER_EMACS_INT) |
| 2761 | XSETINT (val, 0); | 2794 | XSETINT (val, 0); |
| 2762 | else if (XINT (count) > 0) | 2795 | else if (XINT (count) > 0) |
| 2763 | XSETINT (val, (EMACS_UINT) XUINT (value) << XFASTINT (count)); | 2796 | XSETINT (val, XUINT (value) << XFASTINT (count)); |
| 2764 | else if (XINT (count) <= -BITS_PER_EMACS_INT) | 2797 | else if (XINT (count) <= -BITS_PER_EMACS_INT) |
| 2765 | XSETINT (val, 0); | 2798 | XSETINT (val, 0); |
| 2766 | else | 2799 | else |
| 2767 | XSETINT (val, (EMACS_UINT) XUINT (value) >> -XINT (count)); | 2800 | XSETINT (val, XUINT (value) >> -XINT (count)); |
| 2768 | return val; | 2801 | return val; |
| 2769 | } | 2802 | } |
| 2770 | 2803 | ||