mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Trap INT64_MIN / -1 exception
This commit is contained in:
		| @@ -85,7 +85,8 @@ static const JanetAbstractType bi_uint64_type = { | ||||
|  | ||||
| static int parse_int64(const char *str, bi_int64 *box) { | ||||
|     char *endptr; | ||||
|     int base = (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) ? 16 : 10; | ||||
|     int base = ((str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) || | ||||
|                 (str[0] == '-' && str[1] == '0' && (str[2] == 'x' || str[2] == 'X'))) ? 16 : 10; | ||||
|     errno = 0; | ||||
|     *box = (bi_int64)strtoll(str, &endptr, base); | ||||
|     if ((errno == ERANGE && (*box == LLONG_MAX || *box == LLONG_MIN)) || | ||||
| @@ -239,6 +240,33 @@ static Janet cfun_##type##_##name##_mut(int32_t argc, Janet *argv) { \ | ||||
|     return janet_wrap_abstract(box); \ | ||||
| } | ||||
|  | ||||
| #define DIVMETHOD_SIGNED(type,name,oper) \ | ||||
| static Janet cfun_##type##_##name(int32_t argc, Janet *argv) { \ | ||||
|     janet_arity(argc, 2, -1);                       \ | ||||
|     bi_##type *box = (bi_##type *)janet_abstract(&bi_##type##_type, sizeof(bi_##type)); \ | ||||
|     *box = check_bi_##type(argv[0]); \ | ||||
|     for (int i=1;i<argc;i++) { \ | ||||
|       bi_##type value =  check_bi_##type(argv[i]); \ | ||||
|       if (value == 0) janet_panic("division by zero"); \ | ||||
|       if ((value == -1) && (*box == INT64_MIN)) janet_panic("INT64_MIN divided by -1"); \ | ||||
|       *box oper##= check_bi_##type(argv[i]); \ | ||||
|     } \ | ||||
|     return janet_wrap_abstract(box); \ | ||||
| } \ | ||||
|  \ | ||||
| static Janet cfun_##type##_##name##_mut(int32_t argc, Janet *argv) { \ | ||||
|     janet_arity(argc, 2, -1); \ | ||||
|     bi_##type *box = (bi_##type *)janet_getabstract(argv,0,&bi_##type##_type); \ | ||||
|     for (int i=1;i<argc;i++) { \ | ||||
|       bi_##type value =  check_bi_##type(argv[i]); \ | ||||
|       if (value == 0) janet_panic("division by zero"); \ | ||||
|       if ((value == -1) && (*box == INT64_MIN)) janet_panic("INT64_MIN divided by -1"); \ | ||||
|       *box oper##= check_bi_##type(argv[i]); \ | ||||
|     } \ | ||||
|     return janet_wrap_abstract(box); \ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #define COMPMETHOD(type,name,oper) \ | ||||
| @@ -254,8 +282,8 @@ static Janet cfun_##type##_##name(int32_t argc, Janet *argv) { \ | ||||
| OPMETHOD(int64, add, +) | ||||
| OPMETHOD(int64, sub, -) | ||||
| OPMETHOD(int64, mul, *) | ||||
| DIVMETHOD(int64, div, /) | ||||
| DIVMETHOD(int64, mod, %) | ||||
| DIVMETHOD_SIGNED(int64, div, /) | ||||
| DIVMETHOD_SIGNED(int64, mod, %) | ||||
| OPMETHOD(int64, and, &) | ||||
| OPMETHOD(int64, or, |) | ||||
| OPMETHOD(int64, xor, ^) | ||||
| @@ -287,6 +315,7 @@ COMPMETHOD(uint64, ne, !=) | ||||
|  | ||||
| #undef OPMETHOD | ||||
| #undef DIVMETHOD | ||||
| #undef DIVMETHOD_SIGNED | ||||
| #undef COMPMETHOD | ||||
|  | ||||
| static JanetMethod int64_methods[] = { | ||||
|   | ||||
| @@ -23,44 +23,70 @@ | ||||
|  | ||||
| # some tests for bigint  | ||||
|  | ||||
| (def i64 bigint/int64) | ||||
| (def u64 bigint/uint64) | ||||
|  | ||||
| (assert-no-error | ||||
|  "create some uint64 bigints" | ||||
|  (do | ||||
|    # from number | ||||
|    (def a (bigint/uint64 10)) | ||||
|    (def a (u64 10)) | ||||
|    # max double we can convert to int (2^53) | ||||
|    (def b (bigint/uint64 0x1fffffffffffff)) | ||||
|    (def b (bigint/uint64 (math/pow 2 53))) | ||||
|    (def b (u64 0x1fffffffffffff)) | ||||
|    (def b (u64 (math/pow 2 53))) | ||||
|    # from string  | ||||
|    (def c (bigint/uint64 "0xffffffffffffffff")) | ||||
|    (def d (bigint/uint64 "123456789")))) | ||||
|    (def c (u64 "0xffffffffffffffff")) | ||||
|    (def d (u64 "123456789")))) | ||||
|  | ||||
| (assert-no-error | ||||
|  "create some int64 bigints" | ||||
|  (do | ||||
|    # from number | ||||
|    (def a (bigint/int64 -10)) | ||||
|    (def a (i64 -10)) | ||||
|    # max double we can convert to int (2^53) | ||||
|    (def b (bigint/int64 0x1fffffffffffff)) | ||||
|    (def b (bigint/int64 (math/pow 2 53))) | ||||
|    (def b (i64 0x1fffffffffffff)) | ||||
|    (def b (i64 (math/pow 2 53))) | ||||
|    # from string  | ||||
|    (def c (bigint/int64 "0x7fffffffffffffff")) | ||||
|    (def d (bigint/int64 "123456789")))) | ||||
|    (def c (i64 "0x7fffffffffffffff")) | ||||
|    (def d (i64 "123456789")))) | ||||
|  | ||||
| (assert-error | ||||
|  "bad initializers" | ||||
|  (do | ||||
|    # double to big to be converted to uint64 without truncation (2^53 + 1) | ||||
|    (def b (bigint/uint64 (+ 0xffff_ffff_ffff_ff 1))) | ||||
|    (def b (bigint/uint64 (+ (math/pow 2 53) 1))) | ||||
|    (def b (u64 (+ 0xffff_ffff_ffff_ff 1))) | ||||
|    (def b (u64 (+ (math/pow 2 53) 1))) | ||||
|    # out of range 65 bits | ||||
|    (def c (bigint/uint64 "0x1ffffffffffffffff")) | ||||
|    (def c (u64 "0x1ffffffffffffffff")) | ||||
|    # just to big      | ||||
|    (def d (bigint/uint64 "123456789123456789123456789")))) | ||||
|    (def d (u64 "123456789123456789123456789")))) | ||||
|  | ||||
| (assert (:== (:/ (u64 "0xffffffffffffffff") 8 2) "0xfffffffffffffff") "bigint operations") | ||||
| (assert (let [a (u64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations") | ||||
|  | ||||
| (assert-error | ||||
|  "trap INT64_MIN / -1" | ||||
|  (:/ (bigint/int64 "-0x8000000000000000") -1)) | ||||
|  | ||||
| # in place operators | ||||
| (assert (let [a (u64 1e10)] (:+! a 1000000 "1000000" "0xffff") (:== a 10002065535)) "in place operators") | ||||
|  | ||||
| # int64 typed arrays | ||||
| (assert (let [t (tarray/new :int64 10) | ||||
|               b (i64 1000)] | ||||
|           (set (t 0) 1000) | ||||
|           (set (t 1) b) | ||||
|           (set (t 2) "1000") | ||||
|           (set (t 3) (t 0)) | ||||
|           (set (t 4) (u64 1000)) | ||||
|           (and  | ||||
|            (:== (t 0) (t 1)) | ||||
|            (:== (t 1) (t 2)) | ||||
|            (:== (t 2) (t 3)) | ||||
|            (:== (t 3) (t 4)) | ||||
|            )) | ||||
|         "int64 typed arrays") | ||||
|  | ||||
| (assert (:== (:/ (bigint/uint64 "0xffffffffffffffff") 8 2) "0xfffffffffffffff") "bigint operations") | ||||
| (assert (let [a (bigint/uint64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations") | ||||
|          | ||||
|  | ||||
|  | ||||
| (end-suite) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 J.-F. Cap
					J.-F. Cap