mirror of
https://github.com/fmtlib/fmt.git
synced 2026-04-30 19:09:22 +08:00
Don't assume nul termination in printf
Thanks ZUENS2020 for reporting.
This commit is contained in:
parent
ea85b81ccd
commit
dc05bee307
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
@ -48,6 +48,8 @@ jobs:
|
|||||||
- cxx: clang++-14
|
- cxx: clang++-14
|
||||||
build_type: Debug
|
build_type: Debug
|
||||||
std: 20
|
std: 20
|
||||||
|
cxxflags: -fsanitize=address
|
||||||
|
cxxflags_extra: -fno-sanitize-recover=all -fno-omit-frame-pointer
|
||||||
- cxx: clang++-14
|
- cxx: clang++-14
|
||||||
build_type: Debug
|
build_type: Debug
|
||||||
std: 20
|
std: 20
|
||||||
@ -154,7 +156,7 @@ jobs:
|
|||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
env:
|
env:
|
||||||
CXX: ${{matrix.cxx}}
|
CXX: ${{matrix.cxx}}
|
||||||
CXXFLAGS: ${{matrix.cxxflags}}
|
CXXFLAGS: ${{matrix.cxxflags}} ${{matrix.cxxflags_extra}}
|
||||||
run: |
|
run: |
|
||||||
cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
cmake -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
||||||
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
|
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
|
||||||
|
|||||||
@ -330,6 +330,7 @@ template <typename Char, typename GetArg>
|
|||||||
auto parse_header(const Char*& it, const Char* end, format_specs& specs,
|
auto parse_header(const Char*& it, const Char* end, format_specs& specs,
|
||||||
GetArg get_arg) -> int {
|
GetArg get_arg) -> int {
|
||||||
int arg_index = -1;
|
int arg_index = -1;
|
||||||
|
if (it == end) return arg_index;
|
||||||
Char c = *it;
|
Char c = *it;
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
// Parse an argument index (if followed by '$') or a width possibly
|
// Parse an argument index (if followed by '$') or a width possibly
|
||||||
|
|||||||
@ -268,22 +268,6 @@ TEST(util_test, format_system_error) {
|
|||||||
fmt::format_system_error(message, EDOM, "test");
|
fmt::format_system_error(message, EDOM, "test");
|
||||||
auto ec = std::error_code(EDOM, std::generic_category());
|
auto ec = std::error_code(EDOM, std::generic_category());
|
||||||
EXPECT_EQ(to_string(message), std::system_error(ec, "test").what());
|
EXPECT_EQ(to_string(message), std::system_error(ec, "test").what());
|
||||||
message = fmt::memory_buffer();
|
|
||||||
|
|
||||||
// Check if std::allocator throws on allocating max size_t / 2 chars.
|
|
||||||
size_t max_size = max_value<size_t>() / 2;
|
|
||||||
bool throws_on_alloc = false;
|
|
||||||
try {
|
|
||||||
auto alloc = std::allocator<char>();
|
|
||||||
alloc.deallocate(alloc.allocate(max_size), max_size);
|
|
||||||
} catch (const std::bad_alloc&) {
|
|
||||||
throws_on_alloc = true;
|
|
||||||
}
|
|
||||||
if (!throws_on_alloc) {
|
|
||||||
fmt::print(stderr, "warning: std::allocator allocates {} chars\n",
|
|
||||||
max_size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(util_test, system_error) {
|
TEST(util_test, system_error) {
|
||||||
|
|||||||
@ -313,7 +313,8 @@ TEST(printf_test, positional_precision) {
|
|||||||
EXPECT_EQ("Hell", test_sprintf("%2$.*1$s", 4, "Hello"));
|
EXPECT_EQ("Hell", test_sprintf("%2$.*1$s", 4, "Hello"));
|
||||||
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d", 5.0, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d", 5.0, 42), format_error,
|
||||||
"precision is not integer");
|
"precision is not integer");
|
||||||
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d"), format_error, "argument not found");
|
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d"), format_error,
|
||||||
|
"argument not found");
|
||||||
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d", big_num, 42), format_error,
|
EXPECT_THROW_MSG(test_sprintf("%2$.*1$d", big_num, 42), format_error,
|
||||||
"number is too big");
|
"number is too big");
|
||||||
}
|
}
|
||||||
@ -322,7 +323,8 @@ TEST(printf_test, positional_width_and_precision) {
|
|||||||
EXPECT_EQ(" 00042", test_sprintf("%3$*1$.*2$d", 7, 5, 42));
|
EXPECT_EQ(" 00042", test_sprintf("%3$*1$.*2$d", 7, 5, 42));
|
||||||
EXPECT_EQ(" ab", test_sprintf("%3$*1$.*2$s", 7, 2, "abcdef"));
|
EXPECT_EQ(" ab", test_sprintf("%3$*1$.*2$s", 7, 2, "abcdef"));
|
||||||
EXPECT_EQ(" 00042", test_sprintf("%3$*1$.*2$x", 7, 5, 0x42));
|
EXPECT_EQ(" 00042", test_sprintf("%3$*1$.*2$x", 7, 5, 0x42));
|
||||||
EXPECT_EQ("100.4400000", test_sprintf("%6$-*5$.*4$f%3$s%2$s%1$s", "", "", "", 7, 4, 100.44));
|
EXPECT_EQ("100.4400000",
|
||||||
|
test_sprintf("%6$-*5$.*4$f%3$s%2$s%1$s", "", "", "", 7, 4, 100.44));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> struct make_signed {
|
template <typename T> struct make_signed {
|
||||||
@ -555,3 +557,8 @@ TEST(printf_test, make_printf_args) {
|
|||||||
fmt::vsprintf(fmt::basic_string_view<wchar_t>(L"[%d] %s happened"),
|
fmt::vsprintf(fmt::basic_string_view<wchar_t>(L"[%d] %s happened"),
|
||||||
{fmt::make_printf_args<wchar_t>(n, L"something")}));
|
{fmt::make_printf_args<wchar_t>(n, L"something")}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(printf_test, trailing_percent_non_nul_terminated) {
|
||||||
|
auto p = std::unique_ptr<char>(new char('%'));
|
||||||
|
EXPECT_THROW(fmt::sprintf(fmt::string_view(p.get(), 1)), format_error);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user