mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 20:00:19 +02:00
Avoid undefined behavior regarding signed integers and left shifts.
* libguile/numbers.c (scm_logbit_p): If the requested bit is the sign bit (or above), check the sign portably. Otherwise, ensure that we're testing the bit in a two's complement representation. (left_shift_exact_integer): Avoid left-shifting negative integers. * libguile/vm-i-scheme.c (ash): Avoid left-shifting negative integers.
This commit is contained in:
parent
5fbf0e0f99
commit
03cce0ce5f
2 changed files with 17 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
|||
/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
* 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
||||
* 2013 Free Software Foundation, Inc.
|
||||
* 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
|
||||
* 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
|
||||
* and Bellcore. See scm_divide.
|
||||
|
@ -4680,9 +4680,15 @@ SCM_DEFINE (scm_logbit_p, "logbit?", 2, 0, 0,
|
|||
|
||||
if (SCM_I_INUMP (j))
|
||||
{
|
||||
/* bits above what's in an inum follow the sign bit */
|
||||
iindex = min (iindex, SCM_LONG_BIT - 1);
|
||||
return scm_from_bool ((1L << iindex) & SCM_I_INUM (j));
|
||||
if (iindex < SCM_LONG_BIT - 1)
|
||||
/* Arrange for the number to be converted to unsigned before
|
||||
checking the bit, to ensure that we're testing the bit in a
|
||||
two's complement representation (regardless of the native
|
||||
representation. */
|
||||
return scm_from_bool ((1UL << iindex) & SCM_I_INUM (j));
|
||||
else
|
||||
/* Portably check the sign. */
|
||||
return scm_from_bool (SCM_I_INUM (j) < 0);
|
||||
}
|
||||
else if (SCM_BIGP (j))
|
||||
{
|
||||
|
@ -4992,7 +4998,7 @@ left_shift_exact_integer (SCM n, long count)
|
|||
else if (count < SCM_I_FIXNUM_BIT-1 &&
|
||||
((scm_t_bits) (SCM_SRS (nn, (SCM_I_FIXNUM_BIT-1 - count)) + 1)
|
||||
<= 1))
|
||||
return SCM_I_MAKINUM (nn << count);
|
||||
return SCM_I_MAKINUM (nn < 0 ? -(-nn << count) : (nn << count));
|
||||
else
|
||||
{
|
||||
SCM result = scm_i_inum2big (nn);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013,
|
||||
* 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
|
@ -505,7 +506,9 @@ VM_DEFINE_FUNCTION (159, ash, "ash", 2)
|
|||
&& ((scm_t_bits)
|
||||
(SCM_SRS (nn, (SCM_I_FIXNUM_BIT-1 - bits_to_shift)) + 1)
|
||||
<= 1))
|
||||
RETURN (SCM_I_MAKINUM (nn << bits_to_shift));
|
||||
RETURN (SCM_I_MAKINUM (nn < 0
|
||||
? -(-nn << bits_to_shift)
|
||||
: (nn << bits_to_shift)));
|
||||
/* fall through */
|
||||
}
|
||||
/* fall through */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue