fix overflow in << and >>

This commit is contained in:
Vítor Santos Costa 2011-11-16 07:36:34 +00:00
parent c2504af4fb
commit 67820baee0
2 changed files with 72 additions and 34 deletions

View File

@ -10257,7 +10257,7 @@ Yap_absmi(int inp)
if (IsIntTerm(d0) && IsIntTerm(d1)) {
Int i2 = IntOfTerm(d1);
if (i2 < 0)
d0 = MkIntegerTerm(IntOfTerm(d0) >> -i2);
d0 = MkIntegerTerm(SLR(IntOfTerm(d0), -i2));
else
d0 = do_sll(IntOfTerm(d0),i2);
}
@ -10343,7 +10343,7 @@ Yap_absmi(int inp)
if (IsIntTerm(d0)) {
Int i2 = IntOfTerm(d0);
if (i2 < 0)
d0 = MkIntegerTerm(d1 >> -i2);
d0 = MkIntegerTerm(SLR(d1, -i2));
else
d0 = do_sll(d1,i2);
}
@ -10388,7 +10388,7 @@ Yap_absmi(int inp)
if (IsIntTerm(d0) && IsIntTerm(d1)) {
Int i2 = IntOfTerm(d1);
if (i2 < 0)
d0 = MkIntegerTerm(IntOfTerm(d0) >> -i2);
d0 = MkIntegerTerm(SLR(IntOfTerm(d0), -i2));
else
d0 = do_sll(IntOfTerm(d0),i2);
}
@ -10481,7 +10481,7 @@ Yap_absmi(int inp)
if (IsIntTerm(d0)) {
Int i2 = IntOfTerm(d0);
if (i2 < 0)
d0 = MkIntegerTerm(d1 >> -i2);
d0 = MkIntegerTerm(SLR(d1, -i2));
else
d0 = do_sll(d1,i2);
}
@ -10531,7 +10531,7 @@ Yap_absmi(int inp)
if (i2 < 0)
d0 = do_sll(IntOfTerm(d0), -i2);
else
d0 = MkIntTerm(IntOfTerm(d0) >> i2);
d0 = MkIntTerm(SLR(IntOfTerm(d0), i2));
}
else {
saveregs();
@ -10576,7 +10576,7 @@ Yap_absmi(int inp)
{
Int d1 = PREG->u.xxn.c;
if (IsIntTerm(d0)) {
d0 = MkIntTerm(IntOfTerm(d0) >> d1);
d0 = MkIntTerm(SLR(IntOfTerm(d0), d1));
}
else {
saveregs();
@ -10617,7 +10617,7 @@ Yap_absmi(int inp)
if (i2 < 0)
d0 = do_sll(d1, -i2);
else
d0 = MkIntegerTerm(d1 >> i2);
d0 = MkIntegerTerm(SLR(d1, i2));
}
else {
saveregs();
@ -10662,7 +10662,7 @@ Yap_absmi(int inp)
if (i2 < 0)
d0 = do_sll(IntOfTerm(d0), -i2);
else
d0 = MkIntTerm(IntOfTerm(d0) >> i2);
d0 = MkIntTerm(SLR(IntOfTerm(d0), i2));
}
else {
saveregs();
@ -10710,7 +10710,7 @@ Yap_absmi(int inp)
{
Int d1 = PREG->u.yxn.c;
if (IsIntTerm(d0)) {
d0 = MkIntTerm(IntOfTerm(d0) >> d1);
d0 = MkIntTerm(SLR(IntOfTerm(d0), d1));
}
else {
saveregs();
@ -10753,7 +10753,7 @@ Yap_absmi(int inp)
if (i2 < 0)
d0 = do_sll(d1, -i2);
else
d0 = MkIntegerTerm(d1 >> i2);
d0 = MkIntegerTerm(SLR(d1, i2));
}
else {
saveregs();

View File

@ -69,6 +69,12 @@ sub_int(Int i, Int j)
#endif
}
inline static Int
SLR(Int i, Int shift)
{
return (shift < sizeof(Int)*8-1 ? shift : (i >= 0 ? 0 : -1));
}
#ifdef __GNUC__
#ifdef __i386__
#define DO_MULTI() { Int tmp1; \
@ -114,28 +120,56 @@ times_int(Int i1, Int i2) {
}
#if USE_GMP
static inline int
sl_overflow(Int i,Int j)
#ifndef __GNUC__X
static int
clrsb(Int i)
{
Int x = (8*sizeof(CELL)-2)-j;
CELL t = (1<<x)-1;
Int j=0;
if (x < 0) return TRUE;
t = (1<<x)-1;
return (t & i) != i;
if (i < 0) {
if (i == Int_MIN)
return 1;
i = -i;
}
#if SIZEOF_INT_P == 8
if (i < (Int)(0x100000000)) { j += 32;}
else i >>= 32;
#endif
if (i < (Int)(0x10000)) {j += 16;}
else i >>= 16;
if (i < (Int)(0x100)) {j += 8;}
else i >>= 8;
if (i < (Int)(0x10)) {j += 4;}
else i >>= 4;
if (i < (Int)(0x4)) {j += 2;}
else i >>= 2;
if (i < (Int)(0x2)) j++;
return j;
}
#endif
inline static Term
do_sll(Int i, Int j)
do_sll(Int i, Int j) /* j > 0 */
{
Int k;
#ifdef USE_GMP
if (sl_overflow(i,j)) {
return Yap_gmp_sll_ints(i, j);
}
if (
#ifdef __GNUC__X
#if SIZEOF_LONG_INT < SIZEOF_INT_P
__builtin_clrsbll(i)
#else
__builtin_clrsbl(i)
#endif
#else
clrsb(i)
#endif
> j)
RINT(i << j);
return Yap_gmp_sll_ints(i, j);
#else
RINT(i << j);
#endif
}
@ -459,14 +493,16 @@ p_sll(Term t1, Term t2) {
switch (ETypeOfTerm(t2)) {
case long_int_e:
/* two integers */
if (IntegerOfTerm(t2) < 0) {
Int i2 = IntegerOfTerm(t2);
if (i2 == Int_MIN) {
return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2");
{ Int i2 = IntegerOfTerm(t2);
if (i2 <= 0) {
if (i2 == Int_MIN) {
return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2");
}
RINT(SLR(IntegerOfTerm(t1), -i2));
}
RINT(IntegerOfTerm(t1) >> -i2);
return do_sll(IntegerOfTerm(t1),i2);
}
return do_sll(IntegerOfTerm(t1),IntegerOfTerm(t2));
case double_e:
return Yap_ArithError(TYPE_ERROR_INTEGER, t2, "<</2");
case big_int_e:
@ -505,14 +541,16 @@ p_slr(Term t1, Term t2) {
switch (ETypeOfTerm(t2)) {
case long_int_e:
/* two integers */
if (IntegerOfTerm(t2) < 0) {
Int i2 = IntegerOfTerm(t2);
if (i2 == Int_MIN) {
return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2");
{ Int i2 = IntegerOfTerm(t2);
if (i2 < 0) {
if (i2 == Int_MIN) {
return Yap_ArithError(RESOURCE_ERROR_HUGE_INT, t2, ">>/2");
}
return do_sll(IntegerOfTerm(t1), -i2);
}
return do_sll(IntegerOfTerm(t1), -i2);
RINT(SLR(IntegerOfTerm(t1), i2));
}
RINT(IntegerOfTerm(t1) >> IntegerOfTerm(t2));
case double_e:
return Yap_ArithError(TYPE_ERROR_INTEGER, t2, ">>/2");
case big_int_e: