mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-16 16:50:21 +02:00
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.
This commit is contained in:
parent
0bd659658b
commit
d2295ba571
1 changed files with 18 additions and 14 deletions
|
@ -490,6 +490,7 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
|
||||||
#undef INIT
|
#undef INIT
|
||||||
#undef INUM_MAX
|
#undef INUM_MAX
|
||||||
#undef INUM_MIN
|
#undef INUM_MIN
|
||||||
|
#undef INUM_STEP
|
||||||
#undef jump_table
|
#undef jump_table
|
||||||
#undef LOCAL_REF
|
#undef LOCAL_REF
|
||||||
#undef LOCAL_SET
|
#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)
|
do { LOCAL_SET (dst, x); NEXT (1); } while (0)
|
||||||
|
|
||||||
/* The maximum/minimum tagged integers. */
|
/* The maximum/minimum tagged integers. */
|
||||||
#define INUM_MAX (INTPTR_MAX - 1)
|
#define INUM_MAX \
|
||||||
#define INUM_MIN (INTPTR_MIN + scm_tc2_int)
|
((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) \
|
#define BINARY_INTEGER_OP(CFUNC,SFUNC) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -2807,15 +2813,14 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
|
||||||
{
|
{
|
||||||
ARGS1 (x);
|
ARGS1 (x);
|
||||||
|
|
||||||
/* Check for overflow. */
|
/* Check for overflow. We must avoid overflow in the signed
|
||||||
if (SCM_LIKELY ((scm_t_intptr) SCM_UNPACK (x) < INUM_MAX))
|
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;
|
SCM result;
|
||||||
|
|
||||||
/* Add the integers without untagging. */
|
/* Add 1 to the integer without untagging. */
|
||||||
result = SCM_PACK ((scm_t_intptr) SCM_UNPACK (x)
|
result = SCM_PACK ((scm_t_signed_bits) SCM_UNPACK (x) + INUM_STEP);
|
||||||
+ (scm_t_intptr) SCM_UNPACK (SCM_I_MAKINUM (1))
|
|
||||||
- scm_tc2_int);
|
|
||||||
|
|
||||||
if (SCM_LIKELY (SCM_I_INUMP (result)))
|
if (SCM_LIKELY (SCM_I_INUMP (result)))
|
||||||
RETURN (result);
|
RETURN (result);
|
||||||
|
@ -2842,15 +2847,14 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
|
||||||
{
|
{
|
||||||
ARGS1 (x);
|
ARGS1 (x);
|
||||||
|
|
||||||
/* Check for underflow. */
|
/* Check for overflow. We must avoid overflow in the signed
|
||||||
if (SCM_LIKELY ((scm_t_intptr) SCM_UNPACK (x) > INUM_MIN))
|
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;
|
SCM result;
|
||||||
|
|
||||||
/* Substract the integers without untagging. */
|
/* Substract 1 from the integer without untagging. */
|
||||||
result = SCM_PACK ((scm_t_intptr) SCM_UNPACK (x)
|
result = SCM_PACK ((scm_t_signed_bits) SCM_UNPACK (x) - INUM_STEP);
|
||||||
- (scm_t_intptr) SCM_UNPACK (SCM_I_MAKINUM (1))
|
|
||||||
+ scm_tc2_int);
|
|
||||||
|
|
||||||
if (SCM_LIKELY (SCM_I_INUMP (result)))
|
if (SCM_LIKELY (SCM_I_INUMP (result)))
|
||||||
RETURN (result);
|
RETURN (result);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue