Skip to content

Commit

Permalink
Fix 128 bit decoding and add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
filmor committed Mar 12, 2024
1 parent 4bc7cf8 commit 3b9f99a
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
16 changes: 9 additions & 7 deletions rustler/src/types/i128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 16 additions & 2 deletions rustler_tests/test/primitives_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

0 comments on commit 3b9f99a

Please sign in to comment.