[libcxx-commits] [libcxx] [libc++][format] Discard contents since null-terminator in character arrays in formatting (PR #116571)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 20 11:38:25 PST 2025


================
@@ -189,14 +197,19 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu
     return basic_format_arg<_Context>{__arg, static_cast<unsigned long long>(__value)};
   else if constexpr (__arg == __arg_t::__string_view)
     // Using std::size on a character array will add the NUL-terminator to the size.
-    if constexpr (is_array_v<_Dp>)
-      return basic_format_arg<_Context>{
-          __arg, basic_string_view<typename _Context::char_type>{__value, extent_v<_Dp> - 1}};
-    else
-      // When the _Traits or _Allocator are different an implicit conversion will
-      // fail.
-      return basic_format_arg<_Context>{
-          __arg, basic_string_view<typename _Context::char_type>{__value.data(), __value.size()}};
+    if constexpr (__is_bounded_array_of<_Dp, __context_char_type>) {
+      const auto __pbegin = std::begin(__value);
+      if (const __context_char_type* const __pzero =
+              char_traits<__context_char_type>::find(__pbegin, extent_v<_Dp>, __context_char_type{})) {
+        return basic_format_arg<_Context>{
+            __arg, basic_string_view<__context_char_type>{__pbegin, static_cast<size_t>(__pzero - __pbegin)}};
+      } else {
+        // Per [format.arg]/5, the behavior is undefined because the array is not null-terminated.
+        return basic_format_arg<_Context>{__arg, basic_string_view<__context_char_type>{__pbegin, extent_v<_Dp>}};
----------------
ldionne wrote:

If this is UB, instead shouldn't we do this?

```
if constexpr (__is_bounded_array_of<_Dp, __context_char_type>) {
  const __context_char_type* const __pzero = char_traits<__context_char_type>::find(__pbegin, extent_v<_Dp>, __context_char_type{});
  _LIBCPP_ASSERT_VALID_RANGE(__pzero != nullptr, "we'd read out of bounds");
  return basic_format_arg<_Context>{__arg, basic_string_view<__context_char_type>{__pbegin, static_cast<size_t>(__pzero - __pbegin)}};
```

and then drop the `else` that currently says `// Per [format.arg]/5, the behavior is undefined because the array is not null-terminated.`. WDYT?

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


More information about the libcxx-commits mailing list