[libcxx-commits] [libcxx] [libc++] Fix possible out of range access in bitset::to_ullong implementation (PR #121348)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 3 12:54:06 PST 2025


================
@@ -381,8 +382,9 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
   unsigned long long __r = __first_[0];
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
-  for (size_t __i = 1; __i < sizeof(unsigned long long) / sizeof(__storage_type); ++__i)
-    __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT);
+  size_t __n_words = std::min<size_t>(_N_words, sizeof(unsigned long long) / sizeof(__storage_type));
----------------
winner245 wrote:

The problem is that gdb cannot resolve the name `__bits_per_word` if I do not explicitly reference it within the member initializer list of the constructor. However, since I already do a pre-truncation in the derived class (`std::bitset`) constructor, I do not need a redundant truncation in the base class (`__bitset<1, _Size>`) constructor. Thus, my current solution is to explicitly reference `__bits_per_word` but unconditionally use `__v`. 

```cpp
template <size_t _Size>
inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
    : __first_(_Size == __bits_per_word ? static_cast<__storage_type>(__v) : static_cast<__storage_type>(__v)) {}
```

This change fixes the CI failure. 

https://github.com/llvm/llvm-project/pull/121348


More information about the libcxx-commits mailing list