diff options
author | Mark H Weaver <mhw@netris.org> | 2013-08-03 14:46:40 -0400 |
---|---|---|
committer | Mark H Weaver <mhw@netris.org> | 2013-08-03 14:46:40 -0400 |
commit | cb1482e719a41182e3beec062ff6844c2ee19498 (patch) | |
tree | 55255d3f03de8251cd0bc29f13c028a2ced4b3a0 /libguile/vm-i-scheme.c | |
parent | 478fa0d53026f5420de5a1dab8b4f46e67138deb (diff) | |
download | guile-cb1482e719a41182e3beec062ff6844c2ee19498.tar.gz |
VM: Avoid signed overflows in 'add1' and 'sub1'.
* libguile/vm-i-scheme.c (INUM_STEP): New macro.
(add1, sub1): Avoid signed overflows, and use INUM_STEP.
Diffstat (limited to 'libguile/vm-i-scheme.c')
-rw-r--r-- | libguile/vm-i-scheme.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/libguile/vm-i-scheme.c b/libguile/vm-i-scheme.c index edd783ef5..d52eec76c 100644 --- a/libguile/vm-i-scheme.c +++ b/libguile/vm-i-scheme.c @@ -207,10 +207,14 @@ VM_DEFINE_FUNCTION (149, ge, "ge?", 2) /* The maximum/minimum tagged integers. */ #undef INUM_MAX #undef INUM_MIN +#undef INUM_STEP #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)) #undef FUNC2 #define FUNC2(CFUNC,SFUNC) \ @@ -294,15 +298,14 @@ VM_DEFINE_FUNCTION (151, add1, "add1", 1) { 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); @@ -328,15 +331,14 @@ VM_DEFINE_FUNCTION (153, sub1, "sub1", 1) { 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); |