summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2013-08-06 17:00:23 -0400
committerMark H Weaver <mhw@netris.org>2013-08-06 17:00:23 -0400
commitd2295ba5716b60a5f0b28b1b91fd2ed3cf1192f5 (patch)
treeebe1383ae6d82f2e5ced130c5506c7a80c5b2193
parent0bd659658ba2a2b6dab9cb75f693818e5ce8241b (diff)
downloadguile-d2295ba5716b60a5f0b28b1b91fd2ed3cf1192f5.tar.gz
RTL VM: Avoid signed overflows in 'add1' and 'sub1'.
* libguile/vm-engine.c (INUM_MIN, INUM_MAX): Redefine without making assumptions about the representation. (INUM_STEP): New macro. (add1, sub1): Avoid signed overflows, and use INUM_STEP.
-rw-r--r--libguile/vm-engine.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index ec14bd79a..9f3ff5679 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -490,6 +490,7 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
#undef INIT
#undef INUM_MAX
#undef INUM_MIN
+#undef INUM_STEP
#undef jump_table
#undef LOCAL_REF
#undef LOCAL_SET
@@ -754,8 +755,13 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
do { LOCAL_SET (dst, x); NEXT (1); } while (0)
/* The maximum/minimum tagged integers. */
-#define INUM_MAX (INTPTR_MAX - 1)
-#define INUM_MIN (INTPTR_MIN + scm_tc2_int)
+#define INUM_MAX \
+ ((scm_t_signed_bits) SCM_UNPACK (SCM_I_MAKINUM (SCM_MOST_POSITIVE_FIXNUM)))
+#define INUM_MIN \
+ ((scm_t_signed_bits) SCM_UNPACK (SCM_I_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM)))
+#define INUM_STEP \
+ ((scm_t_signed_bits) SCM_UNPACK (SCM_INUM1) \
+ - (scm_t_signed_bits) SCM_UNPACK (SCM_INUM0))
#define BINARY_INTEGER_OP(CFUNC,SFUNC) \
{ \
@@ -2807,15 +2813,14 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
{
ARGS1 (x);
- /* Check for overflow. */
- if (SCM_LIKELY ((scm_t_intptr) SCM_UNPACK (x) < INUM_MAX))
+ /* Check for overflow. We must avoid overflow in the signed
+ addition below, even if X is not an inum. */
+ if (SCM_LIKELY ((scm_t_signed_bits) SCM_UNPACK (x) <= INUM_MAX - INUM_STEP))
{
SCM result;
- /* Add the integers without untagging. */
- result = SCM_PACK ((scm_t_intptr) SCM_UNPACK (x)
- + (scm_t_intptr) SCM_UNPACK (SCM_I_MAKINUM (1))
- - scm_tc2_int);
+ /* Add 1 to the integer without untagging. */
+ result = SCM_PACK ((scm_t_signed_bits) SCM_UNPACK (x) + INUM_STEP);
if (SCM_LIKELY (SCM_I_INUMP (result)))
RETURN (result);
@@ -2842,15 +2847,14 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
{
ARGS1 (x);
- /* Check for underflow. */
- if (SCM_LIKELY ((scm_t_intptr) SCM_UNPACK (x) > INUM_MIN))
+ /* Check for overflow. We must avoid overflow in the signed
+ subtraction below, even if X is not an inum. */
+ if (SCM_LIKELY ((scm_t_signed_bits) SCM_UNPACK (x) >= INUM_MIN + INUM_STEP))
{
SCM result;
- /* Substract the integers without untagging. */
- result = SCM_PACK ((scm_t_intptr) SCM_UNPACK (x)
- - (scm_t_intptr) SCM_UNPACK (SCM_I_MAKINUM (1))
- + scm_tc2_int);
+ /* Substract 1 from the integer without untagging. */
+ result = SCM_PACK ((scm_t_signed_bits) SCM_UNPACK (x) - INUM_STEP);
if (SCM_LIKELY (SCM_I_INUMP (result)))
RETURN (result);