[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 20:34:45 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 07c56fd8c97cc4efa3f7386bc8b80b6795987f8c 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 | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index 6ea53cde5670b3..014448be42fd56 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -382,10 +382,12 @@ __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);
   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;
 }



More information about the libcxx-commits mailing list