Skip to content

Commit 9a1911a

Browse files
Hardening and test
1 parent 0dd86fd commit 9a1911a

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

libcxx/include/__format/format_arg_store.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,12 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu
198198
else if constexpr (__arg == __arg_t::__string_view)
199199
// Using std::size on a character array will add the NUL-terminator to the size.
200200
if constexpr (__is_bounded_array_of<_Dp, __context_char_type>) {
201-
const auto __pbegin = std::begin(__value);
202-
if (const __context_char_type* const __pzero =
203-
char_traits<__context_char_type>::find(__pbegin, extent_v<_Dp>, __context_char_type{})) {
204-
return basic_format_arg<_Context>{
205-
__arg, basic_string_view<__context_char_type>{__pbegin, static_cast<size_t>(__pzero - __pbegin)}};
206-
} else {
207-
// Per [format.arg]/5, the behavior is undefined because the array is not null-terminated.
208-
return basic_format_arg<_Context>{__arg, basic_string_view<__context_char_type>{__pbegin, extent_v<_Dp>}};
209-
}
201+
const __context_char_type* const __pbegin = std::begin(__value);
202+
const __context_char_type* const __pzero =
203+
char_traits<__context_char_type>::find(__pbegin, extent_v<_Dp>, __context_char_type{});
204+
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__pzero != nullptr, "formatting a non-null-terminated array");
205+
return basic_format_arg<_Context>{
206+
__arg, basic_string_view<__context_char_type>{__pbegin, static_cast<size_t>(__pzero - __pbegin)}};
210207
} else
211208
// When the _Traits or _Allocator are different an implicit conversion will fail.
212209
return basic_format_arg<_Context>{__arg, basic_string_view<__context_char_type>{__value.data(), __value.size()}};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <format>
10+
11+
// Formatting non-null-terminated character arrays.
12+
13+
// REQUIRES: std-at-least-c++20, has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
14+
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
15+
16+
#include <format>
17+
18+
#include "check_assertion.h"
19+
20+
int main(int, char**) {
21+
{
22+
const char non_null_terminated[3]{'1', '2', '3'};
23+
TEST_LIBCPP_ASSERT_FAILURE(std::format("{}", non_null_terminated), "formatting a non-null-terminated array");
24+
}
25+
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
26+
{
27+
const wchar_t non_null_terminated[3]{L'1', L'2', L'3'};
28+
TEST_LIBCPP_ASSERT_FAILURE(std::format(L"{}", non_null_terminated), "formatting a non-null-terminated array");
29+
}
30+
#endif
31+
32+
return 0;
33+
}

0 commit comments

Comments
 (0)