mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-18 21:29:19 +02:00
Merge pull request #251 from ilammy/overflow-fixes
Fixed a couple of integer overflows
This commit is contained in:
commit
01df2fec44
3 changed files with 87 additions and 10 deletions
22
bignum.c
22
bignum.c
|
@ -29,7 +29,7 @@ sexp sexp_make_bignum (sexp ctx, sexp_uint_t len) {
|
|||
sexp sexp_fixnum_to_bignum (sexp ctx, sexp a) {
|
||||
sexp res = sexp_make_bignum(ctx, 1);
|
||||
if (!sexp_exceptionp(res)) {
|
||||
sexp_bignum_data(res)[0] = sexp_unbox_fixnum(sexp_fx_abs(a));
|
||||
sexp_bignum_data(res)[0] = sexp_unbox_fx_abs(a);
|
||||
sexp_bignum_sign(res) = sexp_fx_sign(a);
|
||||
}
|
||||
return res;
|
||||
|
@ -326,9 +326,9 @@ sexp sexp_bignum_add_fixnum (sexp ctx, sexp a, sexp b) {
|
|||
sexp_gc_preserve1(ctx, c);
|
||||
c = sexp_copy_bignum(ctx, NULL, a, 0);
|
||||
if (sexp_bignum_sign(c) == sexp_fx_sign(b))
|
||||
c = sexp_bignum_fxadd(ctx, c, sexp_unbox_fixnum(sexp_fx_abs(b)));
|
||||
c = sexp_bignum_fxadd(ctx, c, sexp_unbox_fx_abs(b));
|
||||
else
|
||||
c = sexp_bignum_fxsub(ctx, c, sexp_unbox_fixnum(sexp_fx_abs(b)));
|
||||
c = sexp_bignum_fxsub(ctx, c, sexp_unbox_fx_abs(b));
|
||||
sexp_gc_release1(ctx);
|
||||
return c;
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ sexp sexp_bignum_sub_digits (sexp ctx, sexp dst, sexp a, sexp b) {
|
|||
|
||||
sexp sexp_bignum_add_digits (sexp ctx, sexp dst, sexp a, sexp b) {
|
||||
sexp_uint_t alen=sexp_bignum_hi(a), blen=sexp_bignum_hi(b),
|
||||
carry=0, i, n, *adata, *bdata, *cdata;
|
||||
carry=0, i, old_a, p_sum, *adata, *bdata, *cdata;
|
||||
sexp_gc_var1(c);
|
||||
if (alen < blen) return sexp_bignum_add_digits(ctx, dst, b, a);
|
||||
sexp_gc_preserve1(ctx, c);
|
||||
|
@ -377,9 +377,11 @@ sexp sexp_bignum_add_digits (sexp ctx, sexp dst, sexp a, sexp b) {
|
|||
bdata = sexp_bignum_data(b);
|
||||
cdata = sexp_bignum_data(c);
|
||||
for (i=0; i<blen; i++) {
|
||||
n = adata[i];
|
||||
cdata[i] = n + bdata[i] + carry;
|
||||
carry = (n > (SEXP_UINT_T_MAX - bdata[i] - carry) ? 1 : 0);
|
||||
old_a = adata[i]; /* adata may alias cdata */
|
||||
p_sum = adata[i] + bdata[i];
|
||||
cdata[i] = p_sum + carry;
|
||||
carry = (old_a > (SEXP_UINT_T_MAX - bdata[i]) ? 1 : 0)
|
||||
+ (p_sum > (SEXP_UINT_T_MAX - carry) ? 1 : 0);
|
||||
}
|
||||
for ( ; carry && (i<alen); i++) {
|
||||
carry = (cdata[i] == SEXP_UINT_T_MAX ? 1 : 0);
|
||||
|
@ -599,7 +601,7 @@ sexp sexp_bignum_remainder (sexp ctx, sexp a, sexp b) {
|
|||
}
|
||||
|
||||
sexp sexp_bignum_expt (sexp ctx, sexp a, sexp b) {
|
||||
sexp_sint_t e = sexp_unbox_fixnum(sexp_fx_abs(b));
|
||||
sexp_sint_t e = sexp_unbox_fx_abs(b);
|
||||
sexp_gc_var2(res, acc);
|
||||
sexp_gc_preserve2(ctx, res, acc);
|
||||
res = sexp_fixnum_to_bignum(ctx, SEXP_ONE);
|
||||
|
@ -1390,7 +1392,7 @@ sexp sexp_mul (sexp ctx, sexp a, sexp b) {
|
|||
r = (a==SEXP_ZERO ? a : sexp_make_flonum(ctx, sexp_fixnum_to_double(a)*sexp_flonum_value(b)));
|
||||
break;
|
||||
case SEXP_NUM_FIX_BIG:
|
||||
r = sexp_bignum_fxmul(ctx, NULL, b, sexp_unbox_fixnum(sexp_fx_abs(a)), 0);
|
||||
r = sexp_bignum_fxmul(ctx, NULL, b, sexp_unbox_fx_abs(a), 0);
|
||||
sexp_bignum_sign(r) = sexp_fx_sign(a) * sexp_bignum_sign(b);
|
||||
r = sexp_bignum_normalize(r);
|
||||
break;
|
||||
|
@ -1473,7 +1475,7 @@ sexp sexp_div (sexp ctx, sexp a, sexp b) {
|
|||
tmp = sexp_make_ratio(ctx, a, b);
|
||||
r = sexp_ratio_normalize(ctx, tmp, SEXP_FALSE);
|
||||
#else
|
||||
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)/sexp_bignum_to_double(b));
|
||||
r = sexp_make_flonum(ctx, sexp_fixnum_to_double(a)/sexp_bignum_to_double(b));
|
||||
#endif
|
||||
break;
|
||||
case SEXP_NUM_FLO_FIX:
|
||||
|
|
|
@ -1182,6 +1182,8 @@ SEXP_API sexp sexp_symbol_table[SEXP_SYMBOL_TABLE_SIZE];
|
|||
#define sexp_fx_neg(a) (sexp_make_fixnum(-(sexp_unbox_fixnum(a))))
|
||||
#define sexp_fx_abs(a) ((((sexp_sint_t)a) < 0) ? sexp_fx_neg(a) : a)
|
||||
|
||||
#define sexp_unbox_fx_abs(a) ((((sexp_sint_t)a) < 0) ? -sexp_unbox_fixnum(a) : sexp_unbox_fixnum(a))
|
||||
|
||||
#define sexp_fp_add(x,a,b) (sexp_make_flonum(x, sexp_flonum_value(a) + sexp_flonum_value(b)))
|
||||
#define sexp_fp_sub(x,a,b) (sexp_make_flonum(x, sexp_flonum_value(a) - sexp_flonum_value(b)))
|
||||
#define sexp_fp_mul(x,a,b) (sexp_make_flonum(x, sexp_flonum_value(a) * sexp_flonum_value(b)))
|
||||
|
|
|
@ -143,6 +143,79 @@
|
|||
-9223372036854775808))
|
||||
(sign-combinations M7 (+ 1 (expt 2 64))))
|
||||
|
||||
;; fixnum-bignum boundaries (machine word - 1 bit for sign - 2 bits for tag)
|
||||
|
||||
(test 8191 (- -8191))
|
||||
(test 8192 (- -8192))
|
||||
(test 8193 (- -8193))
|
||||
|
||||
(test 536870911 (- -536870911))
|
||||
(test 536870912 (- -536870912))
|
||||
(test 536870913 (- -536870913))
|
||||
|
||||
(test 2305843009213693951 (- -2305843009213693951))
|
||||
(test 2305843009213693952 (- -2305843009213693952))
|
||||
(test 2305843009213693953 (- -2305843009213693953))
|
||||
|
||||
(test 42535295865117307932921825928971026431 (- -42535295865117307932921825928971026431))
|
||||
(test 42535295865117307932921825928971026432 (- -42535295865117307932921825928971026432))
|
||||
(test 42535295865117307932921825928971026433 (- -42535295865117307932921825928971026433))
|
||||
|
||||
(test '((536879104 -536862720 4398046511104 0 8192)
|
||||
(536862720 -536879104 -4398046511104 0 -8192)
|
||||
(-536862720 536879104 -4398046511104 0 8192)
|
||||
(-536879104 536862720 4398046511104 0 -8192))
|
||||
(sign-combinations (expt 2 13) (expt 2 29)))
|
||||
|
||||
(test '((536879104 536862720 4398046511104 65536 0)
|
||||
(-536862720 -536879104 -4398046511104 -65536 0)
|
||||
(536862720 536879104 -4398046511104 -65536 0)
|
||||
(-536879104 -536862720 4398046511104 65536 0))
|
||||
(sign-combinations (expt 2 29) (expt 2 13)))
|
||||
|
||||
(test '((2305843009750564864 -2305843008676823040 1237940039285380274899124224 0 536870912)
|
||||
(2305843008676823040 -2305843009750564864 -1237940039285380274899124224 0 -536870912)
|
||||
(-2305843008676823040 2305843009750564864 -1237940039285380274899124224 0 536870912)
|
||||
(-2305843009750564864 2305843008676823040 1237940039285380274899124224 0 -536870912))
|
||||
(sign-combinations (expt 2 29) (expt 2 61)))
|
||||
|
||||
(test '((2305843009750564864 2305843008676823040 1237940039285380274899124224 4294967296 0)
|
||||
(-2305843008676823040 -2305843009750564864 -1237940039285380274899124224 -4294967296 0)
|
||||
(2305843008676823040 2305843009750564864 -1237940039285380274899124224 -4294967296 0)
|
||||
(-2305843009750564864 -2305843008676823040 1237940039285380274899124224 4294967296 0))
|
||||
(sign-combinations (expt 2 61) (expt 2 29)))
|
||||
|
||||
(test '((42535295865117307935227668938184720384 -42535295865117307930615982919757332480
|
||||
98079714615416886934934209737619787751599303819750539264 0 2305843009213693952)
|
||||
(42535295865117307930615982919757332480 -42535295865117307935227668938184720384
|
||||
-98079714615416886934934209737619787751599303819750539264 0 -2305843009213693952)
|
||||
(-42535295865117307930615982919757332480 42535295865117307935227668938184720384
|
||||
-98079714615416886934934209737619787751599303819750539264 0 2305843009213693952)
|
||||
(-42535295865117307935227668938184720384 42535295865117307930615982919757332480
|
||||
98079714615416886934934209737619787751599303819750539264 0 -2305843009213693952))
|
||||
(sign-combinations (expt 2 61) (expt 2 125)))
|
||||
|
||||
(test '((42535295865117307935227668938184720384 42535295865117307930615982919757332480
|
||||
98079714615416886934934209737619787751599303819750539264 18446744073709551616 0)
|
||||
(-42535295865117307930615982919757332480 -42535295865117307935227668938184720384
|
||||
-98079714615416886934934209737619787751599303819750539264 -18446744073709551616 0)
|
||||
(42535295865117307930615982919757332480 42535295865117307935227668938184720384
|
||||
-98079714615416886934934209737619787751599303819750539264 -18446744073709551616 0)
|
||||
(-42535295865117307935227668938184720384 -42535295865117307930615982919757332480
|
||||
98079714615416886934934209737619787751599303819750539264 18446744073709551616 0))
|
||||
(sign-combinations (expt 2 125) (expt 2 61)))
|
||||
|
||||
;; Regression tests for an overflow in bignum addition
|
||||
(test 8589869056
|
||||
(+ 4294934528 4294934528))
|
||||
(test 36893488143124135936
|
||||
(+ 18446744071562067968 18446744071562067968))
|
||||
(test 680564733841876926908302470789826871296
|
||||
(+ 340282366920938463454151235394913435648 340282366920938463454151235394913435648))
|
||||
(test 231584178474632390847141970017375815706199686964360189615451793408394491068416
|
||||
(+ 115792089237316195423570985008687907853099843482180094807725896704197245534208
|
||||
115792089237316195423570985008687907853099843482180094807725896704197245534208))
|
||||
|
||||
(test #f (< +nan.0 +nan.0))
|
||||
(test #f (<= +nan.0 +nan.0))
|
||||
(test #f (= +nan.0 +nan.0))
|
||||
|
|
Loading…
Add table
Reference in a new issue