From 71b3bbb7698b13b42c99a4ca66c27db4a6189ff8 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 1 Aug 2026 16:05:51 +0200 Subject: Enforce integral values in slice ranges --- boot/result.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 11 deletions(-) (limited to 'boot/result.cc') diff --git a/boot/result.cc b/boot/result.cc index 4d4c20f..f769625 100644 --- a/boot/result.cc +++ b/boot/result.cc @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #include "elna/boot/result.h" +#include #include namespace elna::boot @@ -340,6 +341,16 @@ namespace elna::boot return written > 1 ? std::nullopt : std::make_optional(rop); } + bool integer_literal::fit_into(const std::size_t target_size) + { + if (fits_in(target_size * CHAR_BIT)) + { + this->m_size = target_size; + return true; + } + return false; + } + bool integer_literal::is_signed() const { return this->m_signed; @@ -350,6 +361,18 @@ namespace elna::boot return this->m_size; } + std::string integer_literal::to_string(const std::uint8_t base) const + { + // +1 sign, +1 null terminator + const size_t buffer_size = mpz_sizeinbase(this->raw, static_cast(base)) + 2; + std::string result(buffer_size, '\0'); + + mpz_get_str(result.data(), base, this->raw); + result.resize(std::strlen(result.c_str())); + + return result; + } + void swap(integer_literal& lhs, integer_literal& rhs) noexcept { mpz_swap(lhs.raw, rhs.raw); @@ -357,22 +380,20 @@ namespace elna::boot std::swap(lhs.m_size, rhs.m_size); } - std::optional integer_literal::check() && + bool integer_literal::fits_in(const std::size_t bits) const { std::size_t required_bits = mpz_sizeinbase(this->raw, 2); - if (!is_negative_minimum()) + if (!is_negative_minimum(bits)) { ++required_bits; // Add one bit for the sign. } - if (required_bits > bits() || (mpz_sgn(this->raw) < 0 && !is_signed())) - { - return std::nullopt; - } - else - { - return std::move(*this); - } + return required_bits <= bits && (mpz_sgn(this->raw) >= 0 || is_signed()); + } + + std::optional integer_literal::check() && + { + return fits_in(bits()) ? std::make_optional(std::move(*this)) : std::nullopt; } bool integer_literal::is_negative_minimum(const std::size_t bits) const @@ -454,5 +475,19 @@ std::size_t std::hash>:: std::size_t std::hash::operator()(const elna::boot::integer_literal& key) const noexcept { - return std::hash{}(key.to()); + if (key.is_signed()) + { + if (auto converted = key.to_signed()) + { + return std::hash{}(*converted); + } + } + else + { + if (auto converted = key.to_unsigned()) + { + return std::hash{}(*converted); + } + } + return 0; } -- cgit v1.2.3