Check pointer type specs are compile time

This commit is contained in:
Victor Zverovich 2017-11-23 10:12:23 -08:00
parent c8a9d902dd
commit b25a029284
4 changed files with 16 additions and 29 deletions

View File

@ -287,17 +287,6 @@ const uint64_t internal::basic_data<T>::POWERS_OF_10_64[] = {
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
FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) {

View File

@ -895,8 +895,6 @@ struct int_traits {
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
// configuration.
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>
class int_type_checker : private ErrorHandler {
public:
@ -2010,8 +2014,7 @@ class arg_formatter_base {
}
void operator()(const void *value) {
if (spec_.type_ && spec_.type_ != 'p')
report_unknown_type(spec_.type_, "pointer");
check_pointer_type_spec(spec_.type_, internal::error_handler());
write_pointer(value);
}
};
@ -3099,7 +3102,7 @@ void basic_writer<Char>::write_str(
// Check if StrChar is convertible to Char.
internal::char_traits<Char>::convert(StrChar());
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();
std::size_t str_size = s.size();
if (str_size == 0 && !str_value)
@ -3288,8 +3291,7 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
}
void on_error() {
internal::report_unknown_type(
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
FMT_THROW(format_error("invalid type specifier"));
}
};
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() {
internal::report_unknown_type(type, "double");
FMT_THROW(format_error("invalid type specifier"));
}
};
spec_handler handler(spec.type());
@ -3813,7 +3815,7 @@ struct formatter<
// TODO
break;
case internal::POINTER:
// TODO
internal::check_pointer_type_spec(type, eh);
break;
case internal::CUSTOM:
// Custom format specifiers should be checked in parse functions of

View File

@ -971,18 +971,13 @@ TEST(FormatterTest, RuntimePrecision) {
template <typename T>
void check_unknown_types(
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}";
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
char c = static_cast<char>(i);
if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
safe_sprintf(format_str, "{0:10%c}", c);
if (std::isprint(static_cast<unsigned char>(c))) {
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);
}
const char *message = "invalid type specifier";
EXPECT_THROW_MSG(format(format_str, value), format_error, message)
<< format_str << " " << message;
}
@ -1346,7 +1341,7 @@ TEST(FormatterTest, Examples) {
EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
EXPECT_THROW_MSG(
format("The answer is {:d}", "forty-two"), format_error,
"unknown format code 'd' for string");
"invalid type specifier");
EXPECT_EQ(L"Cyrillic letter \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", bool);
EXPECT_ERROR("{:s}", "invalid type specifier", double);
EXPECT_ERROR("{:s}", "invalid type specifier", void*);
#endif
EXPECT_ERROR("{foo", "missing '}' in format string", int);
EXPECT_ERROR("{10000000000}", "number is too big");

View File

@ -205,7 +205,7 @@ TEST(PrintfTest, Width) {
// Width cannot be specified twice.
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),
format_error, "number is too big");