diff --git a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp index 8a98f0c706f..cd83568abbd 100644 --- a/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp +++ b/Libraries/LibCrypto/BigInt/UnsignedBigInteger.cpp @@ -79,25 +79,19 @@ UnsignedBigInteger UnsignedBigInteger::sub(const UnsignedBigInteger& other) cons } u8 borrow = 0; - for (size_t i = 0; i < other.length(); ++i) { - // This assertion should not fail, because we verified that *this>other at the beginning of the function - ASSERT(!(borrow == 1 && m_words[i] == 0)); - - if (m_words[i] - borrow < other.m_words[i]) { - u64 after_borrow = static_cast(m_words[i] - borrow) + (UINT32_MAX + 1); - result.m_words.append(static_cast(after_borrow - static_cast(other.m_words[i]))); - borrow = 1; - } else { - result.m_words.append(m_words[i] - borrow - other.m_words[i]); - borrow = 0; + for (size_t i = 0; i < length(); ++i) { + u32 other_word = (i < other.length()) ? other.m_words[i] : 0; + i64 temp = static_cast(m_words[i]) - static_cast(other_word) - static_cast(borrow); + // If temp < 0, we had an underflow + borrow = (temp >= 0) ? 0 : 1; + if (temp < 0) { + temp += (UINT32_MAX + 1); } + result.m_words.append(temp); } - for (size_t i = other.length(); i < length(); ++i) { - ASSERT(!(borrow == 1 && m_words[i] == 0)); - result.m_words.append(m_words[i] - borrow); - borrow = 0; - } + // This assertion should not fail, because we verified that *this>=other at the beginning of the function + ASSERT(borrow == 0); return result; } diff --git a/Userland/test-crypto.cpp b/Userland/test-crypto.cpp index f3e8b8598f5..39e0895daae 100644 --- a/Userland/test-crypto.cpp +++ b/Userland/test-crypto.cpp @@ -915,6 +915,15 @@ void bigint_subtraction() // this test only verifies that we don't crash on an assertion PASS; } + { + I_TEST((BigInteger | Subtraction Regerssion 1)); + auto num = Crypto::UnsignedBigInteger { 1 }.shift_left(256); + if (num.sub(1).words() == Vector { 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 0 }) { + PASS; + } else { + FAIL(Incorrect Result); + } + } } void bigint_multiplication()