mirror of
https://github.com/fmtlib/fmt.git
synced 2025-08-01 03:34:45 +02:00
Prevent silent data loss
This commit is contained in:
@@ -2778,6 +2778,11 @@ void check_format_string(S format_str) {
|
|||||||
ignore_unused(error);
|
ignore_unused(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Report truncation to prevent silent data loss.
|
||||||
|
inline void report_truncation(bool truncated) {
|
||||||
|
if (truncated) report_error("output is truncated");
|
||||||
|
}
|
||||||
|
|
||||||
// Use vformat_args and avoid type_identity to keep symbols short and workaround
|
// Use vformat_args and avoid type_identity to keep symbols short and workaround
|
||||||
// a GCC <= 4.8 bug.
|
// a GCC <= 4.8 bug.
|
||||||
template <typename Char = char> struct vformat_args {
|
template <typename Char = char> struct vformat_args {
|
||||||
@@ -2957,9 +2962,16 @@ struct format_to_result {
|
|||||||
/// Specifies if the output was truncated.
|
/// Specifies if the output was truncated.
|
||||||
bool truncated;
|
bool truncated;
|
||||||
|
|
||||||
FMT_CONSTEXPR operator OutputIt&() & noexcept { return out; }
|
FMT_CONSTEXPR operator OutputIt&() & {
|
||||||
FMT_CONSTEXPR operator const OutputIt&() const& noexcept { return out; }
|
detail::report_truncation(truncated);
|
||||||
FMT_CONSTEXPR operator OutputIt&&() && noexcept {
|
return out;
|
||||||
|
}
|
||||||
|
FMT_CONSTEXPR operator const OutputIt&() const& {
|
||||||
|
detail::report_truncation(truncated);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
FMT_CONSTEXPR operator OutputIt&&() && {
|
||||||
|
detail::report_truncation(truncated);
|
||||||
return static_cast<OutputIt&&>(out);
|
return static_cast<OutputIt&&>(out);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -516,8 +516,8 @@ TEST(core_test, constexpr_parse_format_specs) {
|
|||||||
static_assert(parse_test_specs("{42}").width_ref.val.index == 42, "");
|
static_assert(parse_test_specs("{42}").width_ref.val.index == 42, "");
|
||||||
static_assert(parse_test_specs(".42").precision == 42, "");
|
static_assert(parse_test_specs(".42").precision == 42, "");
|
||||||
static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, "");
|
static_assert(parse_test_specs(".{42}").precision_ref.val.index == 42, "");
|
||||||
static_assert(
|
static_assert(parse_test_specs("f").type == fmt::presentation_type::fixed,
|
||||||
parse_test_specs("f").type == fmt::presentation_type::fixed, "");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct test_format_string_handler {
|
struct test_format_string_handler {
|
||||||
@@ -706,7 +706,7 @@ TEST(core_test, format_to) {
|
|||||||
EXPECT_EQ(s, "42");
|
EXPECT_EQ(s, "42");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, format_to_c_array) {
|
TEST(core_test, format_to_array) {
|
||||||
char buffer[4];
|
char buffer[4];
|
||||||
auto result = fmt::format_to(buffer, "{}", 12345);
|
auto result = fmt::format_to(buffer, "{}", 12345);
|
||||||
EXPECT_EQ(4, std::distance(&buffer[0], result.out));
|
EXPECT_EQ(4, std::distance(&buffer[0], result.out));
|
||||||
@@ -714,6 +714,10 @@ TEST(core_test, format_to_c_array) {
|
|||||||
EXPECT_EQ(buffer + 4, result.out);
|
EXPECT_EQ(buffer + 4, result.out);
|
||||||
EXPECT_EQ("1234", fmt::string_view(buffer, 4));
|
EXPECT_EQ("1234", fmt::string_view(buffer, 4));
|
||||||
|
|
||||||
|
char* out = nullptr;
|
||||||
|
EXPECT_THROW(out = result, std::runtime_error);
|
||||||
|
(void)out;
|
||||||
|
|
||||||
result = fmt::format_to(buffer, "{:s}", "foobar");
|
result = fmt::format_to(buffer, "{:s}", "foobar");
|
||||||
EXPECT_EQ(4, std::distance(&buffer[0], result.out));
|
EXPECT_EQ(4, std::distance(&buffer[0], result.out));
|
||||||
EXPECT_TRUE(result.truncated);
|
EXPECT_TRUE(result.truncated);
|
||||||
|
Reference in New Issue
Block a user