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

View File

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