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

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed May 21 10:07:25 PDT 2025


================
@@ -522,12 +571,40 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Siz
 
 template <size_t _Size>
 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::to_ulong() const {
-  return __first_;
+  return __to_ulong(_BoolConstant<_Size <= sizeof(unsigned long) * CHAR_BIT>());
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(false_type) const {
+  if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e)
+    __throw_overflow_error("__bitset<1, _Size>::__to_ulong overflow error");
+
+  return static_cast<unsigned long>(__first_);
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long __bitset<1, _Size>::__to_ulong(true_type) const {
+  return static_cast<unsigned long>(__first_);
 }
 
 template <size_t _Size>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __bitset<1, _Size>::to_ullong() const {
-  return __first_;
+  return __to_ullong(_BoolConstant<_Size <= sizeof(unsigned long long) * CHAR_BIT>());
+}
+
+template <size_t _Size>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
+__bitset<1, _Size>::__to_ullong(false_type) const {
+  if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) != __e)
+    __throw_overflow_error("__bitset<1, _Size>::__to_ullong overflow error");
----------------
ldionne wrote:

```suggestion
  // Handle the case where we have a bitset with leading zeros like 00000000000000101010101010110
  if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true) == __e)
    return static_cast<...>(...);
__throw_overflow_error("__bitset<1, _Size>::__to_ullong overflow error");
```

Flipping this around allows you to document what you're doing here, which is effectively a special case.

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


More information about the libcxx-commits mailing list