Skip to content

Commit 8930d04

Browse files
committed
[libc++][format] Fixes out of bounds access.
Fixes https://llvm.org/PR65011 Reviewed By: #libc, ldionne Differential Revision: https://reviews.llvm.org/D158940
1 parent c2647ed commit 8930d04

File tree

3 files changed

+19
-0
lines changed

3 files changed

+19
-0
lines changed

libcxx/include/__format/format_functions.h

+3
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end,
245245
using _CharT = iter_value_t<_Iterator>;
246246
__format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
247247

248+
if (__r.__last == __end)
249+
std::__throw_format_error("The argument index should end with a ':' or a '}'");
250+
248251
bool __parse = *__r.__last == _CharT(':');
249252
switch (*__r.__last) {
250253
case _CharT(':'):

libcxx/test/std/utilities/format/format.functions/format_tests.h

+5
Original file line numberDiff line numberDiff line change
@@ -3145,8 +3145,13 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
31453145

31463146
// *** Test invalid format strings ***
31473147
check_exception("The format string terminates at a '{'", SV("{"));
3148+
check_exception("The argument index value is too large for the number of arguments supplied", SV("{:"));
31483149
check_exception("The replacement field misses a terminating '}'", SV("{:"), 42);
31493150

3151+
check_exception("The argument index should end with a ':' or a '}'", SV("{0"));
3152+
check_exception("The argument index value is too large for the number of arguments supplied", SV("{0:"));
3153+
check_exception("The replacement field misses a terminating '}'", SV("{0:"), 42);
3154+
31503155
check_exception("The format string contains an invalid escape sequence", SV("}"));
31513156
check_exception("The format string contains an invalid escape sequence", SV("{:}-}"), 42);
31523157

libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ auto test_exception =
5050
};
5151

5252
int main(int, char**) {
53+
#if !defined(TEST_HAS_NO_EXCEPTIONS)
54+
// reproducer of https://llvm.org/PR65011
55+
try {
56+
const char fmt[] = {'{', '0'};
57+
char buf[4096];
58+
[[maybe_unused]] auto ignored =
59+
std::vformat_to(buf, std::string_view{fmt, fmt + sizeof(fmt)}, std::make_format_args());
60+
} catch (...) {
61+
}
62+
#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
63+
5364
format_tests<char, execution_modus::full>(test, test_exception);
5465

5566
#ifndef TEST_HAS_NO_WIDE_CHARACTERS

0 commit comments

Comments
 (0)