-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Fix possible out of range access in bitset #121348
base: main
Are you sure you want to change the base?
Changes from all commits
8af3d5f
654b1e5
54df6ee
d462d7b
a1161b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -136,13 +136,15 @@ 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> | ||||||
# include <__cstddef/ptrdiff_t.h> | ||||||
# include <__cstddef/size_t.h> | ||||||
# include <__functional/hash.h> | ||||||
# include <__functional/unary_function.h> | ||||||
# include <__type_traits/integral_constant.h> | ||||||
# include <__type_traits/is_char_like_type.h> | ||||||
# include <climits> | ||||||
# include <stdexcept> | ||||||
|
@@ -218,10 +220,10 @@ 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 to_ulong(integral_constant < bool, _Size< sizeof(unsigned long) * CHAR_BIT>()); | ||||||
return __to_ulong(_BoolConstant < _Size< sizeof(unsigned long) * CHAR_BIT>()); | ||||||
} | ||||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong() const { | ||||||
return to_ullong(integral_constant < bool, _Size< sizeof(unsigned long long) * CHAR_BIT>()); | ||||||
return __to_ullong(_BoolConstant < _Size< sizeof(unsigned long long) * CHAR_BIT>()); | ||||||
} | ||||||
|
||||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT; | ||||||
|
@@ -233,12 +235,14 @@ private: | |||||
void __init(unsigned long long __v, false_type) _NOEXCEPT; | ||||||
_LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT; | ||||||
# 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 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; | ||||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long to_ullong(true_type, true_type) const; | ||||||
_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; | ||||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long long __to_ullong(true_type, true_type) const; | ||||||
}; | ||||||
|
||||||
template <size_t _N_words, size_t _Size> | ||||||
|
@@ -283,21 +287,30 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned lon | |||||
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_SIZE_T__ == 8 | ||||||
: __first_{__v} | ||||||
# elif __SIZEOF_SIZE_T__ == 4 | ||||||
# if (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 1 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
: __first_{static_cast<__storage_type>(__v)} | ||||||
# elif (__SIZEOF_LONG_LONG__ + __SIZEOF_SIZE_T__ - 1) / __SIZEOF_SIZE_T__ == 2 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
and so on for the other ones below |
||||||
: __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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||||||
: __first_{static_cast<__storage_type>(__v), static_cast<__storage_type>(__v >> __bits_per_word)} | ||||||
# elif _N_words == 3 | ||||||
: __first_{static_cast<__storage_type>(__v), | ||||||
_Size >= 2 * __bits_per_word | ||||||
? static_cast<__storage_type>(__v >> __bits_per_word) | ||||||
: static_cast<__storage_type>((__v >> __bits_per_word) & | ||||||
(__storage_type(1) << (_Size - __bits_per_word)) - 1)} | ||||||
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)>()); | ||||||
__init(__v, _BoolConstant<sizeof(unsigned long long) == sizeof(__storage_type)>()); | ||||||
# endif | ||||||
} | ||||||
|
||||||
|
@@ -338,52 +351,68 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz | |||||
|
||||||
template <size_t _N_words, size_t _Size> | ||||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unsigned long | ||||||
__bitset<_N_words, _Size>::to_ulong(false_type) const { | ||||||
__const_iterator __e = __make_iter(_Size); | ||||||
__const_iterator __i = std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true); | ||||||
if (__i != __e) | ||||||
std::__throw_overflow_error("bitset to_ulong overflow error"); | ||||||
__bitset<_N_words, _Size>::__to_ulong(false_type) const { | ||||||
if (auto __e = __make_iter(_Size); std::find(__make_iter(sizeof(unsigned long) * CHAR_BIT), __e, true) != __e) | ||||||
std::__throw_overflow_error("bitset __to_ulong overflow error"); | ||||||
|
||||||
return __to_ulong(true_type()); | ||||||
} | ||||||
|
||||||
return __first_[0]; | ||||||
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 __to_ulong(true_type(), _BoolConstant<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) const { | ||||||
return __first_[0]; | ||||||
__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") | ||||||
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 { | ||||||
__const_iterator __e = __make_iter(_Size); | ||||||
__const_iterator __i = std::find(__make_iter(sizeof(unsigned long long) * CHAR_BIT), __e, true); | ||||||
if (__i != __e) | ||||||
std::__throw_overflow_error("bitset to_ullong overflow error"); | ||||||
__bitset<_N_words, _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) | ||||||
std::__throw_overflow_error("bitset __to_ullong overflow error"); | ||||||
|
||||||
return to_ullong(true_type()); | ||||||
return __to_ullong(true_type()); | ||||||
} | ||||||
|
||||||
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) const { | ||||||
return to_ullong(true_type(), integral_constant<bool, sizeof(__storage_type) < sizeof(unsigned long long)>()); | ||||||
__bitset<_N_words, _Size>::__to_ullong(true_type) const { | ||||||
return __to_ullong(true_type(), _BoolConstant<sizeof(__storage_type) < sizeof(unsigned long long)>()); | ||||||
} | ||||||
|
||||||
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]; | ||||||
__bitset<_N_words, _Size>::__to_ullong(true_type, false_type) const { | ||||||
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]; | ||||||
__bitset<_N_words, _Size>::__to_ullong(true_type, true_type) const { | ||||||
unsigned long long __r = static_cast<unsigned long long>(__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); | ||||||
const size_t __ull_wrods = (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1; | ||||||
const size_t __n_words = _N_words < __ull_wrods ? _N_words : __ull_wrods; | ||||||
for (size_t __i = 1; __i < __n_words; ++__i) | ||||||
__r |= static_cast<unsigned long long>(__first_[__i]) << (__bits_per_word * __i); | ||||||
_LIBCPP_DIAGNOSTIC_POP | ||||||
return __r; | ||||||
} | ||||||
|
@@ -483,15 +512,18 @@ protected: | |||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT; | ||||||
|
||||||
_LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT; | ||||||
|
||||||
private: | ||||||
_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; | ||||||
}; | ||||||
|
||||||
template <size_t _Size> | ||||||
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_(_Size == __bits_per_word ? static_cast<__storage_type>(__v) : static_cast<__storage_type>(__v)) {} | ||||||
|
||||||
template <size_t _Size> | ||||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void | ||||||
|
@@ -518,12 +550,25 @@ 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 static_cast<unsigned long long>(__first_); | ||||||
} | ||||||
|
||||||
template <size_t _Size> | ||||||
|
@@ -587,8 +632,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; } | ||||||
|
@@ -618,7 +663,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, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current formatting is pretty confusing. I think
clang-format
will let you change the spacing around these brackets without complaining. I'd change to__to_ulong(_BoolConstant<(_Size < sizeof(unsigned long) * CHAR_BIT)>())
.