Skip to content

Commit 95f9692

Browse files
committed
Fix range checking for trunc conversions, f64.convert_u_i32, and add tests.
1 parent d431d59 commit 95f9692

File tree

5 files changed

+170
-25
lines changed

5 files changed

+170
-25
lines changed

ml-proto/src/spec/f32_convert.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ let demote_f64 x =
88
let convert_s_i32 x =
99
make_nan_nondeterministic (F32.of_float (Int32.to_float x))
1010

11+
(*
12+
* Similar to convert_u_i64 below, the high half of the i32 range are beyond
13+
* the range where f32 can represent odd numbers.
14+
*)
1115
let convert_u_i32 x =
1216
make_nan_nondeterministic
1317
(F32.of_float (if x >= Int32.zero then
@@ -18,6 +22,12 @@ let convert_u_i32 x =
1822
let convert_s_i64 x =
1923
make_nan_nondeterministic (F32.of_float (Int64.to_float x))
2024

25+
(*
26+
* Values in the low half of the int64 range can be converted with a signed
27+
* conversion. The high half is beyond the range where f32 can represent odd
28+
* numbers, so we can shift the value right, do a conversion, and then scale it
29+
* back up, without worrying about losing the least-significant digit.
30+
*)
2131
let convert_u_i64 x =
2232
make_nan_nondeterministic
2333
(F32.of_float (if x >= Int64.zero then

ml-proto/src/spec/f64_convert.ml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,25 @@ let promote_f32 x =
88
let convert_s_i32 x =
99
make_nan_nondeterministic (F64.of_float (Int32.to_float x))
1010

11+
(*
12+
* Unlike the other convert_u functions, the high half of the i32 range is
13+
* within the range where f32 can represent odd numbers, so we can't do the
14+
* shift. Instead, we can use int64 signed arithmetic.
15+
*)
1116
let convert_u_i32 x =
1217
make_nan_nondeterministic
13-
(F64.of_float (if x >= Int32.zero then
14-
Int32.to_float x
15-
else
16-
Int32.to_float (Int32.shift_right_logical x 1) *. 2.))
18+
(F64.of_float
19+
(Int64.to_float (Int64.logand (Int64.of_int32 x) 0x00000000ffffffffL)))
1720

1821
let convert_s_i64 x =
1922
make_nan_nondeterministic (F64.of_float (Int64.to_float x))
2023

24+
(*
25+
* Values in the low half of the int64 range can be converted with a signed
26+
* conversion. The high half is beyond the range where f64 can represent odd
27+
* numbers, so we can shift the value right, do a conversion, and then scale it
28+
* back up, without worrying about losing the least-significant digit.
29+
*)
2130
let convert_u_i64 x =
2231
make_nan_nondeterministic
2332
(F64.of_float (if x >= Int64.zero then

ml-proto/src/spec/i32_convert.ml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ let trunc_s_f32 x =
66
if F32.ne x x then
77
raise Numerics.InvalidConversionToInteger
88
else let xf = F32.to_float x in
9-
if xf >= (Int32.to_float Int32.max_int) +. 1. ||
10-
xf <= (Int32.to_float Int32.min_int) -. 1. then
9+
if xf >= -.(Int32.to_float Int32.min_int) ||
10+
xf < (Int32.to_float Int32.min_int) then
1111
raise Numerics.IntegerOverflow
1212
else
1313
Int32.of_float xf
@@ -16,8 +16,8 @@ let trunc_u_f32 x =
1616
if F32.ne x x then
1717
raise Numerics.InvalidConversionToInteger
1818
else let xf = F32.to_float x in
19-
if xf >= (Int32.to_float Int32.max_int) *. 2. +. 2. ||
20-
xf <= -1. then
19+
if xf >= -.(Int32.to_float Int32.min_int) *. 2. ||
20+
xf <= -1. then
2121
raise Numerics.IntegerOverflow
2222
else
2323
Int64.to_int32 (Int64.of_float xf)
@@ -26,8 +26,8 @@ let trunc_s_f64 x =
2626
if F64.ne x x then
2727
raise Numerics.InvalidConversionToInteger
2828
else let xf = F64.to_float x in
29-
if xf >= (Int32.to_float Int32.max_int) +. 1. ||
30-
xf <= (Int32.to_float Int32.min_int) -. 1. then
29+
if xf >= -.(Int32.to_float Int32.min_int) ||
30+
xf < (Int32.to_float Int32.min_int) then
3131
raise Numerics.IntegerOverflow
3232
else
3333
Int32.of_float xf
@@ -36,8 +36,8 @@ let trunc_u_f64 x =
3636
if F64.ne x x then
3737
raise Numerics.InvalidConversionToInteger
3838
else let xf = F64.to_float x in
39-
if xf >= (Int32.to_float Int32.max_int) *. 2. +. 2. ||
40-
xf <= -1. then
39+
if xf >= -.(Int32.to_float Int32.min_int) *. 2. ||
40+
xf <= -1. then
4141
raise Numerics.IntegerOverflow
4242
else
4343
Int64.to_int32 (Int64.of_float xf)

ml-proto/src/spec/i64_convert.ml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ let trunc_s_f32 x =
88
if F32.ne x x then
99
raise Numerics.InvalidConversionToInteger
1010
else let xf = F32.to_float x in
11-
if xf >= (Int64.to_float Int64.max_int) +. 1. ||
12-
xf <= (Int64.to_float Int64.min_int) -. 1. then
11+
if xf >= -.(Int64.to_float Int64.min_int) ||
12+
xf < (Int64.to_float Int64.min_int) then
1313
raise Numerics.IntegerOverflow
1414
else
1515
Int64.of_float xf
@@ -18,10 +18,10 @@ let trunc_u_f32 x =
1818
if F32.ne x x then
1919
raise Numerics.InvalidConversionToInteger
2020
else let xf = F32.to_float x in
21-
if xf >= (Int64.to_float Int64.max_int) *. 2. +. 2. ||
22-
xf <= -1. then
21+
if xf >= -.(Int64.to_float Int64.min_int) *. 2. ||
22+
xf <= -1. then
2323
raise Numerics.IntegerOverflow
24-
else if xf >= (Int64.to_float Int64.max_int) +. 1. then
24+
else if xf >= -.(Int64.to_float Int64.min_int) then
2525
Int64.logxor (Int64.of_float (xf -. 9223372036854775808.)) Int64.min_int
2626
else
2727
Int64.of_float xf
@@ -30,8 +30,8 @@ let trunc_s_f64 x =
3030
if F64.ne x x then
3131
raise Numerics.InvalidConversionToInteger
3232
else let xf = F64.to_float x in
33-
if xf >= (Int64.to_float Int64.max_int) +. 1. ||
34-
xf <= (Int64.to_float Int64.min_int) -. 1. then
33+
if xf >= -.(Int64.to_float Int64.min_int) ||
34+
xf < (Int64.to_float Int64.min_int) then
3535
raise Numerics.IntegerOverflow
3636
else
3737
Int64.of_float xf
@@ -40,10 +40,10 @@ let trunc_u_f64 x =
4040
if F64.ne x x then
4141
raise Numerics.InvalidConversionToInteger
4242
else let xf = F64.to_float x in
43-
if xf >= (Int64.to_float Int64.max_int) *. 2. +. 2. ||
44-
xf <= -1. then
43+
if xf >= -.(Int64.to_float Int64.min_int) *. 2. ||
44+
xf <= -1. then
4545
raise Numerics.IntegerOverflow
46-
else if xf >= (Int64.to_float Int64.max_int) +. 1. then
46+
else if xf >= -.(Int64.to_float Int64.min_int) then
4747
Int64.logxor (Int64.of_float (xf -. 9223372036854775808.)) Int64.min_int
4848
else
4949
Int64.of_float xf

0 commit comments

Comments
 (0)