Skip to content

Commit 75845c0

Browse files
committed
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.
1 parent 88db975 commit 75845c0

2 files changed

Lines changed: 17 additions & 13 deletions

File tree

src/core/inttypes.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,23 +216,22 @@ JANET_CORE_FN(cfun_to_number,
216216

217217
if (janet_abstract_type(abst) == &janet_s64_type) {
218218
int64_t value = *((int64_t*)abst);
219-
if (value > INT32_MAX) {
220-
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
219+
if (value > JANET_INTMAX_INT64) {
220+
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));
221221
}
222-
if (value < INT32_MIN) {
223-
janet_panicf("cannot convert %q to a number, exceededs int32 min", argv[0]);
222+
if (value < -JANET_INTMAX_INT64) {
223+
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));
224224
}
225-
226-
return janet_wrap_integer(value);
225+
return janet_wrap_number((double)value);
227226
}
228227

229228
if (janet_abstract_type(abst) == &janet_u64_type) {
230229
uint64_t value = *((uint64_t*)abst);
231-
if (value > INT32_MAX) {
232-
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
230+
if (value > JANET_INTMAX_INT64) {
231+
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));
233232
}
234233

235-
return janet_wrap_integer(value);
234+
return janet_wrap_number((double)value);
236235
}
237236
}
238237

test/suite0006.janet

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@
4242
# Conversion back to an int32
4343
(assert (= (int/to-number (u64 0xFaFa)) 0xFaFa))
4444
(assert (= (int/to-number (i64 0xFaFa)) 0xFaFa))
45+
(assert (= (int/to-number (u64 9007199254740991)) 9007199254740991))
46+
(assert (= (int/to-number (i64 9007199254740991)) 9007199254740991))
47+
(assert (= (int/to-number (i64 -9007199254740991)) -9007199254740991))
4548

4649
(assert-error
47-
"int64 out of bounds for int32"
48-
(do
49-
(int/to-number (u64 "0x7fff_ffff_ffff_ffff"))
50-
(int/to-number (i64 "-0x7fff_ffff_ffff_ffff"))))
50+
"u64 out of bounds for safe integer"
51+
(int/to-number (u64 "9007199254740993"))
52+
53+
(assert-error
54+
"s64 out of bounds for safe integer"
55+
(int/to-number (i64 "-9007199254740993"))))
5156

5257
(assert-error
5358
"int/to-number fails on non-abstract types"

0 commit comments

Comments
 (0)