[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 19:47:11 PST 2025
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/121348
>From 5e8312285d4d5dd2ebdcef4250c7085786f171ca Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 30 Dec 2024 12:19:19 -0500
Subject: [PATCH 1/3] Improve bitset::to_ullong Implementation
---
libcxx/include/bitset | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 919d2a0f07e096..2f2129bb8cc767 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -133,6 +133,7 @@ template <size_t N> struct hash<std::bitset<N>>;
# include <__algorithm/fill.h>
# include <__algorithm/fill_n.h>
# include <__algorithm/find.h>
+# include <__algorithm/min.h>
# include <__assert>
# include <__bit_reference>
# include <__config>
@@ -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));
+ for (size_t __i = 1; __i < __n_words; ++__i)
+ __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
}
>From c1dfd7900bcc8ecafe73742805c4352bc3a277aa Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Tue, 31 Dec 2024 01:44:59 -0500
Subject: [PATCH 2/3] Make variable constant expression
---
libcxx/include/bitset | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 2f2129bb8cc767..6ea53cde5670b3 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -382,7 +382,8 @@ __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")
- size_t __n_words = std::min<size_t>(_N_words, sizeof(unsigned long long) / sizeof(__storage_type));
+ const size_t __ull_words = sizeof(unsigned long long) / sizeof(__storage_type);
+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
for (size_t __i = 1; __i < __n_words; ++__i)
__r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
_LIBCPP_DIAGNOSTIC_POP
>From f4672bd1bbb5e1f4ce73da3c93ffbdb976abeddd Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 1 Jan 2025 18:06:08 -0500
Subject: [PATCH 3/3] Apply @frederick-vs-ja suggestions to support 16-bit
platforms
---
libcxx/include/bitset | 77 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 65 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 6ea53cde5670b3..f88ba5fe916976 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -233,6 +233,8 @@ private:
# endif // _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type) const;
+ // _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, false_type) const;
+ // _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong(true_type, true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(false_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, false_type) const;
@@ -299,6 +301,36 @@ inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long
# endif
}
+// template <size_t _N_words, size_t _Size>
+// inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
+// # ifndef _LIBCPP_CXX03_LANG
+// # if (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 1
+// : __first_{static_cast<__storage_type>(__v)}
+// # elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 2
+// : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
+// # elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 4
+// # if _N_words == 2
+// : __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)}
+// # elif _N_words == 3
+// : __first_{static_cast<__storage_type>(__v),
+// static_cast<__storage_type>(__v >> __bits_per_word),
+// static_cast<__storage_type>(__v >> (__bits_per_word * 2))}
+// # else
+// : __first_{static_cast<__storage_type>(__v),
+// static_cast<__storage_type>(__v >> __bits_per_word),
+// static_cast<__storage_type>(__v >> (__bits_per_word * 2)),
+// static_cast<__storage_type>(__v >> (__bits_per_word * 3))}
+// # endif
+// # else
+// # error This constructor has not been ported to this platform
+// # endif
+// # endif
+// {
+// # ifdef _LIBCPP_CXX03_LANG
+// __init(__v, integral_constant<bool, sizeof(unsigned long long) == sizeof(__storage_type)>());
+// # endif
+// }
+
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
__bitset<_N_words, _Size>::operator&=(const __bitset& __v) _NOEXCEPT {
@@ -344,15 +376,36 @@ __bitset<_N_words, _Size>::to_ulong(false_type) const {
if (__i != __e)
__throw_overflow_error("bitset to_ulong overflow error");
- return __first_[0];
+ return to_ulong(true_type());
}
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
__bitset<_N_words, _Size>::to_ulong(true_type) const {
return __first_[0];
+ // return to_ulong(true_type(), integral_constant<bool, sizeof(__storage_type) < sizeof(unsigned long)>());
}
+// template <size_t _N_words, size_t _Size>
+// inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
+// __bitset<_N_words, _Size>::to_ulong(true_type, false_type) const {
+// return static_cast<unsigned long>(__first_[0]);
+// }
+
+// template <size_t _N_words, size_t _Size>
+// _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long
+// __bitset<_N_words, _Size>::to_ulong(true_type, true_type) const {
+// unsigned long __r = static_cast<unsigned long>(__first_[0]);
+// _LIBCPP_DIAGNOSTIC_PUSH
+// _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
+// const size_t __ul_words = sizeof(unsigned long) / sizeof(__storage_type);
+// const size_t __n_words = _N_words < __ul_words ? _N_words : __ul_words;
+// for (size_t __i = 1; __i < __n_words; ++__i)
+// __r |= static_cast<unsigned long>(__first_[__i]) << (__bits_per_word * __i);
+// _LIBCPP_DIAGNOSTIC_POP
+// return __r;
+// }
+
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(false_type) const {
@@ -373,19 +426,19 @@ __bitset<_N_words, _Size>::to_ullong(true_type) const {
template <size_t _N_words, size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(true_type, false_type) const {
- return __first_[0];
+ return static_cast<unsigned long long>(__first_[0]);
}
template <size_t _N_words, size_t _Size>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long
__bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
- unsigned long long __r = __first_[0];
+ unsigned long long __r = static_cast<unsigned long long>(__first_[0]);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshift-count-overflow")
const size_t __ull_words = sizeof(unsigned long long) / sizeof(__storage_type);
- const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
+ const size_t __n_words = _N_words < __ull_words ? _N_words : __ull_words;
for (size_t __i = 1; __i < __n_words; ++__i)
- __r |= static_cast<unsigned long long>(__first_[__i]) << (sizeof(__storage_type) * CHAR_BIT * __i);
+ __r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i);
_LIBCPP_DIAGNOSTIC_POP
return __r;
}
@@ -494,8 +547,7 @@ inline _LIBCPP_CONSTEXPR __bitset<1, _Size>::__bitset() _NOEXCEPT : __first_(0)
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) & ((__storage_type(1) << _Size) - 1)) {}
+ : __first_(static_cast<__storage_type>(__v)) {}
template <size_t _Size>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
@@ -524,12 +576,12 @@ 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 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 static_cast<unsigned long long>(__first_);
}
template <size_t _Size>
@@ -595,8 +647,8 @@ protected:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void flip() _NOEXCEPT {}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long to_ulong() const { return 0UL; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { return 0ULL; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return true; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT { return false; }
@@ -626,7 +678,8 @@ public:
// 23.3.5.1 constructors:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset() _NOEXCEPT {}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset(unsigned long long __v) _NOEXCEPT : __base(__v) {}
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset(unsigned long long __v) _NOEXCEPT
+ : __base(sizeof(unsigned long long) * CHAR_BIT <= _Size ? __v : __v & ((1ULL << _Size) - 1)) {}
template <class _CharT, __enable_if_t<_IsCharLikeType<_CharT>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset(
const _CharT* __str,
More information about the libcxx-commits
mailing list