From ef7fdd0f8465ae2ff7bd53afd56895f15088954b Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 10 Dec 2024 18:18:30 +0200 Subject: [PATCH] math.big: fix `assert big.integer_from_int(1) == big.integer_from_bytes([u8(0), 0, 0, 0, 1])` (fix #23115) (#23124) --- vlib/math/big/big_test.v | 20 ++++++++++++++++++++ vlib/math/big/integer.v | 16 ++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/vlib/math/big/big_test.v b/vlib/math/big/big_test.v index e4edabd2c24faf..3f2040d1b7c380 100644 --- a/vlib/math/big/big_test.v +++ b/vlib/math/big/big_test.v @@ -849,3 +849,23 @@ fn test_set_bit() { a.set_bit(100, false) assert a == b } + +fn test_integer_from_bytes_ignores_potential_leading_zero_bytes() { + bint0 := big.integer_from_int(0) + for j in 0 .. 10 { + assert bint0 == big.integer_from_bytes([]u8{len: j}, signum: 1) + assert bint0 == big.integer_from_bytes([]u8{len: j}, signum: 0) + assert bint0 == big.integer_from_bytes([]u8{len: j}, signum: -1) + } + for i in 0 .. 10 { + bint := big.integer_from_int(i) + nbint := big.integer_from_int(-i) + for j in 0 .. 15 { + mut input := []u8{len: j} + input << i + assert bint == big.integer_from_bytes(input) + assert bint == big.integer_from_bytes(input, signum: 1) + assert nbint == big.integer_from_bytes(input, signum: -1) + } + } +} diff --git a/vlib/math/big/integer.v b/vlib/math/big/integer.v index c9b71f1a25d12d..2ee6ee6ed900f7 100644 --- a/vlib/math/big/integer.v +++ b/vlib/math/big/integer.v @@ -126,11 +126,23 @@ pub: // If you want a negative integer, use in the following manner: // `value := big.integer_from_bytes(bytes, signum: -1)` @[direct_array_access] -pub fn integer_from_bytes(input []u8, config IntegerConfig) Integer { +pub fn integer_from_bytes(oinput []u8, config IntegerConfig) Integer { // Thank you to Miccah (@mcastorina) for this implementation and relevant unit tests. - if input.len == 0 { + if oinput.len == 0 { return integer_from_int(0) } + // Ignore leading 0 bytes: + mut first_non_zero_index := -1 + for i in 0 .. oinput.len { + if oinput[i] != 0 { + first_non_zero_index = i + break + } + } + if first_non_zero_index == -1 { + return integer_from_int(0) + } + input := oinput[first_non_zero_index..] // pad input mut padded_input := []u8{len: ((input.len + 3) & ~0x3) - input.len, cap: (input.len + 3) & ~0x3} padded_input << input