[libcxx-commits] [libcxx] [libc++] Fix UB in bitwise logic of {std, ranges}::{fill, fill_n} algorithms (PR #122410)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 20 08:34:56 PST 2025


================
@@ -55,6 +59,25 @@ struct __size_difference_type_traits<_Cp, __void_t<typename _Cp::difference_type
   using size_type       = typename _Cp::size_type;
 };
 
+// This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`,
+// or `unsigned short`. Casting back to _StorageType is crucial to prevent undefined behavior that can arise
+// from integral promotions.
+// See https://github.com/llvm/llvm-project/pull/122410
+template <class _StoragePointer,
+          __enable_if_t<is_unsigned<typename pointer_traits<_StoragePointer>::element_type>::value, int> >
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
+__fill_masked_range(_StoragePointer __word, unsigned __ctz, unsigned __clz, bool __fill_val) {
----------------
ldionne wrote:

I would switch `__ctz` and `__clz`: the leading zeros should probably come before the trailing zeros in the API, since that's the more natural order.

I suggest you apply this change by switching the order of the arguments *but not* switching the call sites. Then, run the tests and see if something fails. If nothing fails, you just found some missing coverage :-). And if things fail, you can go ahead and fix up the call sites. It shouldn't take you much longer than just making the change, but it'll confirm that we have coverage for this!

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


More information about the libcxx-commits mailing list