1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-26 07:03:16 +00:00

int/to-number: restrict input to JANET_INTMAX/MIN

Previously int/to-number would fail if the input was outside
the range of an int32.
Because Janet numbers are doubles,
they can safely store larger ints than an int32.
This commit updates int/to-number to restrict the
value to the range of integers a double can hold, instead of an int32.
This commit is contained in:
Ian Shehadeh 2022-02-21 12:54:38 -05:00
parent 88db9751d7
commit 75845c0283
2 changed files with 17 additions and 13 deletions

View File

@ -216,23 +216,22 @@ JANET_CORE_FN(cfun_to_number,
if (janet_abstract_type(abst) == &janet_s64_type) {
int64_t value = *((int64_t*)abst);
if (value > INT32_MAX) {
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
if (value > JANET_INTMAX_INT64) {
janet_panicf("cannot convert %q to a number, must be in the range [%q, %q]", argv[0], janet_wrap_number(JANET_INTMIN_DOUBLE), janet_wrap_number(JANET_INTMAX_DOUBLE));
}
if (value < INT32_MIN) {
janet_panicf("cannot convert %q to a number, exceededs int32 min", argv[0]);
if (value < -JANET_INTMAX_INT64) {
janet_panicf("cannot convert %q to a number, must be in the range [%q, %q]", argv[0], janet_wrap_number(JANET_INTMIN_DOUBLE), janet_wrap_number(JANET_INTMAX_DOUBLE));
}
return janet_wrap_integer(value);
return janet_wrap_number((double)value);
}
if (janet_abstract_type(abst) == &janet_u64_type) {
uint64_t value = *((uint64_t*)abst);
if (value > INT32_MAX) {
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
if (value > JANET_INTMAX_INT64) {
janet_panicf("cannot convert %q to a number, must be in the range [%q, %q]", argv[0], janet_wrap_number(JANET_INTMIN_DOUBLE), janet_wrap_number(JANET_INTMAX_DOUBLE));
}
return janet_wrap_integer(value);
return janet_wrap_number((double)value);
}
}

View File

@ -42,12 +42,17 @@
# Conversion back to an int32
(assert (= (int/to-number (u64 0xFaFa)) 0xFaFa))
(assert (= (int/to-number (i64 0xFaFa)) 0xFaFa))
(assert (= (int/to-number (u64 9007199254740991)) 9007199254740991))
(assert (= (int/to-number (i64 9007199254740991)) 9007199254740991))
(assert (= (int/to-number (i64 -9007199254740991)) -9007199254740991))
(assert-error
"int64 out of bounds for int32"
(do
(int/to-number (u64 "0x7fff_ffff_ffff_ffff"))
(int/to-number (i64 "-0x7fff_ffff_ffff_ffff"))))
"u64 out of bounds for safe integer"
(int/to-number (u64 "9007199254740993"))
(assert-error
"s64 out of bounds for safe integer"
(int/to-number (i64 "-9007199254740993"))))
(assert-error
"int/to-number fails on non-abstract types"