mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-11 21:38:05 +00:00
Check pointer type specs are compile time
This commit is contained in:
parent
c8a9d902dd
commit
b25a029284
@ -287,17 +287,6 @@ const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
|
|||||||
10000000000000000000ull
|
10000000000000000000ull
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
|
|
||||||
(void)type;
|
|
||||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
|
||||||
FMT_THROW(format_error(
|
|
||||||
format("unknown format code '{}' for {}", code, type)));
|
|
||||||
}
|
|
||||||
FMT_THROW(format_error(
|
|
||||||
format("unknown format code '\\x{:02x}' for {}",
|
|
||||||
static_cast<unsigned>(code), type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FMT_USE_WINDOWS_H
|
#if FMT_USE_WINDOWS_H
|
||||||
|
|
||||||
FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {
|
||||||
|
@ -895,8 +895,6 @@ struct int_traits {
|
|||||||
std::numeric_limits<T>::digits <= 32, uint32_t, uint64_t>::type main_type;
|
std::numeric_limits<T>::digits <= 32, uint32_t, uint64_t>::type main_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
FMT_API FMT_NORETURN void report_unknown_type(char code, const char *type);
|
|
||||||
|
|
||||||
// Static data is placed in this class template to allow header-only
|
// Static data is placed in this class template to allow header-only
|
||||||
// configuration.
|
// configuration.
|
||||||
template <typename T = void>
|
template <typename T = void>
|
||||||
@ -1814,6 +1812,12 @@ constexpr void handle_float_type_spec(char spec, Handler &&handler) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ErrorHandler>
|
||||||
|
constexpr void check_pointer_type_spec(char spec, ErrorHandler &&eh) {
|
||||||
|
if (spec != 0 && spec != 'p')
|
||||||
|
eh.on_error("invalid type specifier");
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ErrorHandler>
|
template <typename ErrorHandler>
|
||||||
class int_type_checker : private ErrorHandler {
|
class int_type_checker : private ErrorHandler {
|
||||||
public:
|
public:
|
||||||
@ -2010,8 +2014,7 @@ class arg_formatter_base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const void *value) {
|
void operator()(const void *value) {
|
||||||
if (spec_.type_ && spec_.type_ != 'p')
|
check_pointer_type_spec(spec_.type_, internal::error_handler());
|
||||||
report_unknown_type(spec_.type_, "pointer");
|
|
||||||
write_pointer(value);
|
write_pointer(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3099,7 +3102,7 @@ void basic_writer<Char>::write_str(
|
|||||||
// Check if StrChar is convertible to Char.
|
// Check if StrChar is convertible to Char.
|
||||||
internal::char_traits<Char>::convert(StrChar());
|
internal::char_traits<Char>::convert(StrChar());
|
||||||
if (spec.type_ && spec.type_ != 's')
|
if (spec.type_ && spec.type_ != 's')
|
||||||
internal::report_unknown_type(spec.type_, "string");
|
FMT_THROW(format_error("invalid type specifier"));
|
||||||
const StrChar *str_value = s.data();
|
const StrChar *str_value = s.data();
|
||||||
std::size_t str_size = s.size();
|
std::size_t str_size = s.size();
|
||||||
if (str_size == 0 && !str_value)
|
if (str_size == 0 && !str_value)
|
||||||
@ -3288,8 +3291,7 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error() {
|
void on_error() {
|
||||||
internal::report_unknown_type(
|
FMT_THROW(format_error("invalid type specifier"));
|
||||||
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
internal::handle_int_type_spec(spec.type(), spec_handler(*this, value, spec));
|
internal::handle_int_type_spec(spec.type(), spec_handler(*this, value, spec));
|
||||||
@ -3333,7 +3335,7 @@ void basic_writer<Char>::write_double(T value, const format_specs &spec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error() {
|
void on_error() {
|
||||||
internal::report_unknown_type(type, "double");
|
FMT_THROW(format_error("invalid type specifier"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spec_handler handler(spec.type());
|
spec_handler handler(spec.type());
|
||||||
@ -3813,7 +3815,7 @@ struct formatter<
|
|||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
case internal::POINTER:
|
case internal::POINTER:
|
||||||
// TODO
|
internal::check_pointer_type_spec(type, eh);
|
||||||
break;
|
break;
|
||||||
case internal::CUSTOM:
|
case internal::CUSTOM:
|
||||||
// Custom format specifiers should be checked in parse functions of
|
// Custom format specifiers should be checked in parse functions of
|
||||||
|
@ -971,18 +971,13 @@ TEST(FormatterTest, RuntimePrecision) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void check_unknown_types(
|
void check_unknown_types(
|
||||||
const T &value, const char *types, const char *type_name) {
|
const T &value, const char *types, const char *type_name) {
|
||||||
char format_str[BUFFER_SIZE], message[BUFFER_SIZE];
|
char format_str[BUFFER_SIZE];
|
||||||
const char *special = ".0123456789}";
|
const char *special = ".0123456789}";
|
||||||
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
|
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
|
||||||
char c = static_cast<char>(i);
|
char c = static_cast<char>(i);
|
||||||
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
|
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
|
||||||
safe_sprintf(format_str, "{0:10%c}", c);
|
safe_sprintf(format_str, "{0:10%c}", c);
|
||||||
if (std::isprint(static_cast<unsigned char>(c))) {
|
const char *message = "invalid type specifier";
|
||||||
safe_sprintf(message, "unknown format code '%c' for %s", c, type_name);
|
|
||||||
} else {
|
|
||||||
safe_sprintf(message, "unknown format code '\\x%02x' for %s", c,
|
|
||||||
type_name);
|
|
||||||
}
|
|
||||||
EXPECT_THROW_MSG(format(format_str, value), format_error, message)
|
EXPECT_THROW_MSG(format(format_str, value), format_error, message)
|
||||||
<< format_str << " " << message;
|
<< format_str << " " << message;
|
||||||
}
|
}
|
||||||
@ -1346,7 +1341,7 @@ TEST(FormatterTest, Examples) {
|
|||||||
EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
|
EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
|
||||||
EXPECT_THROW_MSG(
|
EXPECT_THROW_MSG(
|
||||||
format("The answer is {:d}", "forty-two"), format_error,
|
format("The answer is {:d}", "forty-two"), format_error,
|
||||||
"unknown format code 'd' for string");
|
"invalid type specifier");
|
||||||
|
|
||||||
EXPECT_EQ(L"Cyrillic letter \x42e",
|
EXPECT_EQ(L"Cyrillic letter \x42e",
|
||||||
format(L"Cyrillic letter {}", L'\x42e'));
|
format(L"Cyrillic letter {}", L'\x42e'));
|
||||||
@ -1894,6 +1889,7 @@ TEST(FormatTest, FormatStringErrors) {
|
|||||||
EXPECT_ERROR("{:s}", "invalid type specifier", int);
|
EXPECT_ERROR("{:s}", "invalid type specifier", int);
|
||||||
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
|
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
|
||||||
EXPECT_ERROR("{:s}", "invalid type specifier", double);
|
EXPECT_ERROR("{:s}", "invalid type specifier", double);
|
||||||
|
EXPECT_ERROR("{:s}", "invalid type specifier", void*);
|
||||||
#endif
|
#endif
|
||||||
EXPECT_ERROR("{foo", "missing '}' in format string", int);
|
EXPECT_ERROR("{foo", "missing '}' in format string", int);
|
||||||
EXPECT_ERROR("{10000000000}", "number is too big");
|
EXPECT_ERROR("{10000000000}", "number is too big");
|
||||||
|
@ -205,7 +205,7 @@ TEST(PrintfTest, Width) {
|
|||||||
|
|
||||||
// Width cannot be specified twice.
|
// Width cannot be specified twice.
|
||||||
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), format_error,
|
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), format_error,
|
||||||
"unknown format code '-' for integer");
|
"invalid type specifier");
|
||||||
|
|
||||||
EXPECT_THROW_MSG(fmt::sprintf(format("%{}d", BIG_NUM), 42),
|
EXPECT_THROW_MSG(fmt::sprintf(format("%{}d", BIG_NUM), 42),
|
||||||
format_error, "number is too big");
|
format_error, "number is too big");
|
||||||
|
Loading…
Reference in New Issue
Block a user