From 3b9f99af67d1d9bb89fc80a4fc93130451c56805 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 12 Mar 2024 22:53:29 +0100 Subject: [PATCH] Fix 128 bit decoding and add more tests --- rustler/src/types/i128.rs | 16 +++++++++------- rustler_tests/test/primitives_test.exs | 18 ++++++++++++++++-- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/rustler/src/types/i128.rs b/rustler/src/types/i128.rs index ae76e41b..b79a4d0c 100644 --- a/rustler/src/types/i128.rs +++ b/rustler/src/types/i128.rs @@ -71,16 +71,18 @@ impl<'a> Decoder<'a> for i128 { return Err(Error::BadArg); } - let mut res = [0u8; 16]; - res[16 - n..].copy_from_slice(&input[4..4 + n]); - let res = i128::from_le_bytes(res); - if res < 0 { - // The stored data is supposed to be unsigned, so if we interpret it as negative here, - // it was too large. + let is_pos = input[3] == 0; + + let mut res = [0; 16]; + res[..n].copy_from_slice(&input[4..4 + n]); + + if res[15] >= 128 && is_pos { + // Value is too large for i128 return Err(Error::BadArg); } - if input[3] == 0 { + let res = i128::from_le_bytes(res); + if is_pos { Ok(res) } else { Ok(-res) diff --git a/rustler_tests/test/primitives_test.exs b/rustler_tests/test/primitives_test.exs index 10b8d6fd..d1a8f4f8 100644 --- a/rustler_tests/test/primitives_test.exs +++ b/rustler_tests/test/primitives_test.exs @@ -40,14 +40,25 @@ defmodule RustlerTest.PrimitivesTest do assert i == RustlerTest.echo_i128(i) assert -i == RustlerTest.echo_i128(-i) + i = 1 <<< 80 + assert i == RustlerTest.echo_i128(i) + assert -i == RustlerTest.echo_i128(-i) + i = 1 <<< 126 assert i == RustlerTest.echo_i128(i) assert -i == RustlerTest.echo_i128(-i) + i = -170141183460469231731687303715884105728 # i128::min_value() + assert i == RustlerTest.echo_i128(i) + + i = 170141183460469231731687303715884105727 # i128::max_value() + assert i == RustlerTest.echo_i128(i) + + i = 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF # u128::max_value() assert_raise ArgumentError, fn -> RustlerTest.echo_i128(:non_int) end assert_raise ArgumentError, fn -> RustlerTest.echo_i128(123.45) end - assert_raise ArgumentError, fn -> RustlerTest.echo_i128(1 <<< 127) end assert_raise ArgumentError, fn -> RustlerTest.echo_i128(1 <<< 128) end + assert_raise ArgumentError, fn -> RustlerTest.echo_i128(i) end end test "u128 support" do @@ -59,8 +70,11 @@ defmodule RustlerTest.PrimitivesTest do i = 1 <<< 127 assert i == RustlerTest.echo_u128(i) + i = 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF # u128::max_value() + assert i == RustlerTest.echo_u128(i) + assert_raise ArgumentError, fn -> RustlerTest.echo_u128(:non_int) end assert_raise ArgumentError, fn -> RustlerTest.echo_u128(123.45) end - assert_raise ArgumentError, fn -> RustlerTest.echo_i128(1 <<< 128) end + assert_raise ArgumentError, fn -> RustlerTest.echo_i128(1 <<< 129) end end end