aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorPaul Eggert2011-05-20 22:38:43 -0700
committerPaul Eggert2011-05-20 22:38:43 -0700
commit0ae6bdee0085b05028108325b0a4ce979eadb24e (patch)
tree51746679d14a133e355aeb2effe115db5dd692f5 /src/data.c
parentde883a701d8f0db9595c6c459fdff9e3bb20bc83 (diff)
downloademacs-0ae6bdee0085b05028108325b0a4ce979eadb24e.tar.gz
emacs-0ae6bdee0085b05028108325b0a4ce979eadb24e.zip
* data.c: Avoid integer truncation in expressions involving floats.
* data.c: Include <intprops.h>. (arith_driver): When there's an integer overflow in an expression involving floating point, convert the integers to floating point so that the resulting value does not suffer from catastrophic integer truncation. For example, on a 64-bit host (* 4 most-negative-fixnum 0.5) should yield about -4.6e+18, not zero. Do not rely on undefined behavior after integer overflow.
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}