aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/data.c b/src/data.c
index 577ae777d89..073fb0d4926 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,47 @@ 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 overflow = 1;
2498 accum = (EMACS_UINT) accum * (EMACS_UINT) next & INTMASK;
2499 }
2500 else
2501 accum *= next;
2473 break; 2502 break;
2474 case Adiv: 2503 case Adiv:
2475 if (!argnum) 2504 if (!argnum)
@@ -2501,6 +2530,9 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
2501 } 2530 }
2502 } 2531 }
2503 2532
2533 accum &= INTMASK;
2534 if (MOST_POSITIVE_FIXNUM < accum)
2535 accum += MOST_NEGATIVE_FIXNUM - (MOST_POSITIVE_FIXNUM + 1);
2504 XSETINT (val, accum); 2536 XSETINT (val, accum);
2505 return val; 2537 return val;
2506} 2538}