Fix out-of-range integers with the 'c' presentation type (#4839)

Formatting an integer with ':c' used the magnitude (abs_value) and never
range-checked, so negatives were mangled and out-of-range values silently
truncated. Copy the value as a character and report an error when it is out
of range, treating all character types as unsigned for portability.
This commit is contained in:
Victor Zverovich
2026-07-17 11:36:52 -07:00
parent d45179c1e7
commit 7852fc384c
2 changed files with 21 additions and 2 deletions
+10
View File
@@ -1334,6 +1334,16 @@ TEST(format_test, format_int) {
"invalid format specifier");
check_unknown_types(42, "bBdoxXnLc", "integer");
EXPECT_EQ(fmt::format("{:c}", static_cast<int>('x')), "x");
// The 'c' type treats all character types as unsigned for portability, so the
// representable range for char is [0, 255] and out-of-range values are
// reported as an error.
EXPECT_EQ(fmt::format("{:c}", 200), std::string(1, static_cast<char>(200)));
EXPECT_EQ(fmt::format("{:c}", 255), std::string(1, static_cast<char>(255)));
const char* msg = "character value out of range";
EXPECT_THROW_MSG((void)fmt::format("{:c}", -1), format_error, msg);
EXPECT_THROW_MSG((void)fmt::format("{:c}", -104), format_error, msg);
EXPECT_THROW_MSG((void)fmt::format("{:c}", 256), format_error, msg);
EXPECT_THROW_MSG((void)fmt::format("{:c}", 400u), format_error, msg);
}
TEST(format_test, format_bin) {