mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 14:17:36 +00:00
LibCrypto: Make constructing a BigInteger from string fallible
Previously, constructing a `UnsignedBigInteger::from_base()` could produce an incorrect result if the input string contained a valid Base36 digit that was out of range of the given base. The same method would also crash if the input string contained an invalid Base36 digit. An error is now returned in both these cases. Constructing a BigFraction from string is now also fallible, so that we can handle the case where we are given an input string with invalid digits.
This commit is contained in:
parent
0b0c7693e2
commit
48a3a02238
11 changed files with 68 additions and 57 deletions
|
@ -35,7 +35,7 @@ size_t SignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) cons
|
|||
return m_unsigned_data.export_data(bytes_view, remove_leading_zeros) + 1;
|
||||
}
|
||||
|
||||
SignedBigInteger SignedBigInteger::from_base(u16 N, StringView str)
|
||||
ErrorOr<SignedBigInteger> SignedBigInteger::from_base(u16 N, StringView str)
|
||||
{
|
||||
auto sign = false;
|
||||
if (str.length() > 1) {
|
||||
|
@ -47,8 +47,8 @@ SignedBigInteger SignedBigInteger::from_base(u16 N, StringView str)
|
|||
if (maybe_sign == '+')
|
||||
str = str.substring_view(1);
|
||||
}
|
||||
auto unsigned_data = UnsignedBigInteger::from_base(N, str);
|
||||
return { move(unsigned_data), sign };
|
||||
auto unsigned_data = TRY(UnsignedBigInteger::from_base(N, str));
|
||||
return SignedBigInteger { move(unsigned_data), sign };
|
||||
}
|
||||
|
||||
ErrorOr<String> SignedBigInteger::to_base(u16 N) const
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
[[nodiscard]] static SignedBigInteger from_base(u16 N, StringView str);
|
||||
[[nodiscard]] static ErrorOr<SignedBigInteger> from_base(u16 N, StringView str);
|
||||
[[nodiscard]] ErrorOr<String> to_base(u16 N) const;
|
||||
[[nodiscard]] ByteString to_base_deprecated(u16 N) const;
|
||||
|
||||
|
@ -171,5 +171,5 @@ struct AK::Formatter<Crypto::SignedBigInteger> : AK::Formatter<Crypto::UnsignedB
|
|||
inline Crypto::SignedBigInteger
|
||||
operator""_sbigint(char const* string, size_t length)
|
||||
{
|
||||
return Crypto::SignedBigInteger::from_base(10, { string, length });
|
||||
return MUST(Crypto::SignedBigInteger::from_base(10, { string, length }));
|
||||
}
|
||||
|
|
|
@ -132,16 +132,22 @@ size_t UnsignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) co
|
|||
return out;
|
||||
}
|
||||
|
||||
UnsignedBigInteger UnsignedBigInteger::from_base(u16 N, StringView str)
|
||||
ErrorOr<UnsignedBigInteger> UnsignedBigInteger::from_base(u16 N, StringView str)
|
||||
{
|
||||
VERIFY(N <= 36);
|
||||
UnsignedBigInteger result;
|
||||
UnsignedBigInteger base { N };
|
||||
|
||||
for (auto& c : str) {
|
||||
for (auto const& c : str) {
|
||||
if (c == '_')
|
||||
continue;
|
||||
result = result.multiplied_by(base).plus(parse_ascii_base36_digit(c));
|
||||
if (!is_ascii_base36_digit(c))
|
||||
return Error::from_string_literal("Invalid Base36 digit");
|
||||
auto digit = parse_ascii_base36_digit(c);
|
||||
if (digit >= N)
|
||||
return Error::from_string_literal("Base36 digit out of range");
|
||||
|
||||
result = result.multiplied_by(base).plus(digit);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
size_t export_data(Bytes, bool remove_leading_zeros = false) const;
|
||||
|
||||
[[nodiscard]] static UnsignedBigInteger from_base(u16 N, StringView str);
|
||||
[[nodiscard]] static ErrorOr<UnsignedBigInteger> from_base(u16 N, StringView str);
|
||||
[[nodiscard]] ErrorOr<String> to_base(u16 N) const;
|
||||
[[nodiscard]] ByteString to_base_deprecated(u16 N) const;
|
||||
|
||||
|
@ -161,5 +161,5 @@ struct AK::Formatter<Crypto::UnsignedBigInteger> : Formatter<StringView> {
|
|||
inline Crypto::UnsignedBigInteger
|
||||
operator""_bigint(char const* string, size_t length)
|
||||
{
|
||||
return Crypto::UnsignedBigInteger::from_base(10, { string, length });
|
||||
return MUST(Crypto::UnsignedBigInteger::from_base(10, { string, length }));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue