0
0
mirror of https://github.com/llvm/llvm-project.git synced 2025-04-21 12:56:52 +00:00

[libc++][format] Fixes out of bounds access.

Fixes https://llvm.org/PR65011

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D158940

(cherry picked from commit 8930d04d5580c6a2cf04545c87387cd150cd7b46)
This commit is contained in:
Mark de Wever 2023-08-26 19:25:45 +02:00 committed by Tobias Hieta
parent 4a999da214
commit 078e20cade
3 changed files with 19 additions and 0 deletions
libcxx
include/__format
test/std/utilities/format/format.functions

@ -245,6 +245,9 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end,
using _CharT = iter_value_t<_Iterator>;
__format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
if (__r.__last == __end)
std::__throw_format_error("The argument index should end with a ':' or a '}'");
bool __parse = *__r.__last == _CharT(':');
switch (*__r.__last) {
case _CharT(':'):

@ -3145,8 +3145,13 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
// *** Test invalid format strings ***
check_exception("The format string terminates at a '{'", SV("{"));
check_exception("The argument index value is too large for the number of arguments supplied", SV("{:"));
check_exception("The replacement field misses a terminating '}'", SV("{:"), 42);
check_exception("The argument index should end with a ':' or a '}'", SV("{0"));
check_exception("The argument index value is too large for the number of arguments supplied", SV("{0:"));
check_exception("The replacement field misses a terminating '}'", SV("{0:"), 42);
check_exception("The format string contains an invalid escape sequence", SV("}"));
check_exception("The format string contains an invalid escape sequence", SV("{:}-}"), 42);

@ -50,6 +50,17 @@ auto test_exception =
};
int main(int, char**) {
#if !defined(TEST_HAS_NO_EXCEPTIONS)
// reproducer of https://llvm.org/PR65011
try {
const char fmt[] = {'{', '0'};
char buf[4096];
[[maybe_unused]] auto ignored =
std::vformat_to(buf, std::string_view{fmt, fmt + sizeof(fmt)}, std::make_format_args());
} catch (...) {
}
#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
format_tests<char, execution_modus::full>(test, test_exception);
#ifndef TEST_HAS_NO_WIDE_CHARACTERS