[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
Thu Jan 2 05:59:53 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:

I have revised the code and added support for 16-bit systems. Specifically, I modified the ULL ctor and the `to_ullong` and `to_ulong` functions. The ULL ctor is a bit ugly because we now need to consider `sizeof(unsigned long long) / sizeof(size_t) == 4` combined with the possibility of `_N_words < 4`. This added complexity could be well integrated into a cleaner loop as done in the `to_ullong` function. However, constexpr loops are not supported in C++11, and the standard requires this ctor to be constexpr since C++11. The implementations of the `to_ullong` and `to_ulong` functions are much cleaner and valid for a wider range of platforms with any different ratio values `sizeof(unsigned long long) / sizeof(size_t)`. 

Currently, I am encountering a CI failure from the Python script `libcxx/utils/gdb/libcxx/printers.py`, which reports:

> gdb.error: There is no member or method named __bits_per_word.
> {<std::__1::__bitset<1, 15>> = {__first_ = 1020}, static __n_words = 1}

It is a gdb test initiated by `libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp`, which calls `StdBitsetPrinter::__init__` in `libcxx/utils/gdb/libcxx/printers.py` and encountered the failure while executing line 396 `self.bits_per_word = int(self.val["__bits_per_word"])`. I couldn't figure out what may have caused this failure as I didn't touch `__bits_per_word`. The `__bits_per_word` is a static data member in the base class `__bitset<_N_words, _Size>` and its specializations `__bitset<1, _Size>` and `__bitset<0, 0>`. Do you have any idea what might be causing this error?

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


More information about the libcxx-commits mailing list