mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-24 12:14:26 +00:00
Disallow formatting of multibyte strings into a wide buffer (#606)
This commit is contained in:
parent
3851994ab0
commit
6570dc3122
@ -1112,7 +1112,7 @@ enum type {
|
|||||||
INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
|
INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
|
||||||
// followed by floating-point types.
|
// followed by floating-point types.
|
||||||
DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
|
DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
|
||||||
CSTRING, STRING, TSTRING, POINTER, CUSTOM
|
CSTRING, STRING, POINTER, CUSTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool is_integral(type t) {
|
constexpr bool is_integral(type t) {
|
||||||
@ -1189,10 +1189,10 @@ template <> constexpr type get_type<unsigned char *>() { return CSTRING; }
|
|||||||
template <> constexpr type get_type<const unsigned char *>() { return CSTRING; }
|
template <> constexpr type get_type<const unsigned char *>() { return CSTRING; }
|
||||||
template <> constexpr type get_type<std::string>() { return STRING; }
|
template <> constexpr type get_type<std::string>() { return STRING; }
|
||||||
template <> constexpr type get_type<string_view>() { return STRING; }
|
template <> constexpr type get_type<string_view>() { return STRING; }
|
||||||
template <> constexpr type get_type<wchar_t *>() { return TSTRING; }
|
template <> constexpr type get_type<wchar_t *>() { return CSTRING; }
|
||||||
template <> constexpr type get_type<const wchar_t *>() { return TSTRING; }
|
template <> constexpr type get_type<const wchar_t *>() { return CSTRING; }
|
||||||
template <> constexpr type get_type<std::wstring>() { return TSTRING; }
|
template <> constexpr type get_type<std::wstring>() { return STRING; }
|
||||||
template <> constexpr type get_type<wstring_view>() { return TSTRING; }
|
template <> constexpr type get_type<wstring_view>() { return STRING; }
|
||||||
template <> constexpr type get_type<void *>() { return POINTER; }
|
template <> constexpr type get_type<void *>() { return POINTER; }
|
||||||
template <> constexpr type get_type<const void *>() { return POINTER; }
|
template <> constexpr type get_type<const void *>() { return POINTER; }
|
||||||
template <> constexpr type get_type<std::nullptr_t>() { return POINTER; }
|
template <> constexpr type get_type<std::nullptr_t>() { return POINTER; }
|
||||||
@ -1225,10 +1225,9 @@ class value {
|
|||||||
double double_value;
|
double double_value;
|
||||||
long double long_double_value;
|
long double long_double_value;
|
||||||
const void *pointer;
|
const void *pointer;
|
||||||
string_value<char> string;
|
string_value<char_type> string;
|
||||||
string_value<signed char> sstring;
|
string_value<signed char> sstring;
|
||||||
string_value<unsigned char> ustring;
|
string_value<unsigned char> ustring;
|
||||||
string_value<char_type> tstring;
|
|
||||||
custom_value<char_type> custom;
|
custom_value<char_type> custom;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1271,18 +1270,16 @@ class value {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
value(char *s) { set<CSTRING>(string.value, s); }
|
// Formatting of wide strings into a narrow buffer and multibyte strings
|
||||||
value(const char *s) { set<CSTRING>(string.value, s); }
|
// into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606).
|
||||||
value(signed char *s) { set<CSTRING>(sstring.value, s); }
|
value(char_type *s) { set<CSTRING>(string.value, s); }
|
||||||
value(const signed char *s) { set<CSTRING>(sstring.value, s); }
|
value(const char_type *s) { set<CSTRING>(string.value, s); }
|
||||||
value(unsigned char *s) { set<CSTRING>(ustring.value, s); }
|
value(signed char *s) { set_cstring(sstring.value, s); }
|
||||||
value(const unsigned char *s) { set<CSTRING>(ustring.value, s); }
|
value(const signed char *s) { set_cstring(sstring.value, s); }
|
||||||
value(string_view s) { set_string(s); }
|
value(unsigned char *s) { set_cstring(ustring.value, s); }
|
||||||
value(const std::string &s) { set_string(s); }
|
value(const unsigned char *s) { set_cstring(ustring.value, s); }
|
||||||
value(wstring_view s) { set_wstring(s); }
|
value(basic_string_view<char_type> s) { set_string(s); }
|
||||||
value(const std::wstring &s) { set_wstring(s); }
|
value(const std::basic_string<char_type> &s) { set_string(s); }
|
||||||
value(wchar_t *s) { set_wstring(wstring_view(s)); }
|
|
||||||
value(const wchar_t *s) { set_wstring(wstring_view(s)); }
|
|
||||||
|
|
||||||
// Formatting of arbitrary pointers is disallowed. If you want to output a
|
// Formatting of arbitrary pointers is disallowed. If you want to output a
|
||||||
// pointer cast it to "void *" or "const void *". In particular, this forbids
|
// pointer cast it to "void *" or "const void *". In particular, this forbids
|
||||||
@ -1338,12 +1335,11 @@ class value {
|
|||||||
string.size = value.size();
|
string.size = value.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename U>
|
||||||
void set_wstring(const T &value) {
|
constexpr void set_cstring(T &field, const U *str) {
|
||||||
require_wchar<char_type>();
|
static_assert(std::is_same<char, char_type>::value,
|
||||||
static_assert(get_type<T>() == TSTRING, "invalid type");
|
"incompatible string types");
|
||||||
tstring.value = value.data();
|
set<CSTRING>(field, str);
|
||||||
tstring.size = value.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formats an argument of a custom type, such as a user-defined class.
|
// Formats an argument of a custom type, such as a user-defined class.
|
||||||
@ -1439,10 +1435,8 @@ constexpr typename std::result_of<Visitor(int)>::type
|
|||||||
case internal::CSTRING:
|
case internal::CSTRING:
|
||||||
return vis(arg.value_.string.value);
|
return vis(arg.value_.string.value);
|
||||||
case internal::STRING:
|
case internal::STRING:
|
||||||
return vis(string_view(arg.value_.string.value, arg.value_.string.size));
|
|
||||||
case internal::TSTRING:
|
|
||||||
return vis(basic_string_view<Char>(
|
return vis(basic_string_view<Char>(
|
||||||
arg.value_.tstring.value, arg.value_.tstring.size));
|
arg.value_.string.value, arg.value_.string.size));
|
||||||
case internal::POINTER:
|
case internal::POINTER:
|
||||||
return vis(arg.value_.pointer);
|
return vis(arg.value_.pointer);
|
||||||
case internal::CUSTOM:
|
case internal::CUSTOM:
|
||||||
@ -1902,22 +1896,6 @@ class arg_formatter_base {
|
|||||||
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
|
writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StrChar>
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_same<Char, wchar_t>::value &&
|
|
||||||
std::is_same<StrChar, wchar_t>::value>::type
|
|
||||||
write_str(basic_string_view<StrChar> value) {
|
|
||||||
writer_.write_str(value, spec_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename StrChar>
|
|
||||||
typename std::enable_if<
|
|
||||||
!std::is_same<Char, wchar_t>::value ||
|
|
||||||
!std::is_same<StrChar, wchar_t>::value>::type
|
|
||||||
write_str(basic_string_view<StrChar> ) {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
basic_writer<Char> &writer() { return writer_; }
|
basic_writer<Char> &writer() { return writer_; }
|
||||||
format_specs &spec() { return spec_; }
|
format_specs &spec() { return spec_; }
|
||||||
@ -1926,9 +1904,9 @@ class arg_formatter_base {
|
|||||||
writer_.write_str(string_view(value ? "true" : "false"), spec_);
|
writer_.write_str(string_view(value ? "true" : "false"), spec_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const char *value) {
|
void write(const Char *value) {
|
||||||
writer_.write_str(
|
writer_.write_str(basic_string_view<Char>(
|
||||||
string_view(value, value != 0 ? std::strlen(value) : 0), spec_);
|
value, value != 0 ? std::char_traits<Char>::length(value) : 0), spec_);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1985,20 +1963,16 @@ class arg_formatter_base {
|
|||||||
*out = internal::char_traits<Char>::cast(value);
|
*out = internal::char_traits<Char>::cast(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const char *value) {
|
void operator()(const Char *value) {
|
||||||
if (spec_.type_ == 'p')
|
if (spec_.type_ == 'p')
|
||||||
return write_pointer(value);
|
return write_pointer(value);
|
||||||
write(value);
|
write(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(string_view value) {
|
void operator()(basic_string_view<Char> value) {
|
||||||
writer_.write_str(value, spec_);
|
writer_.write_str(value, spec_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(basic_string_view<wchar_t> value) {
|
|
||||||
write_str(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(const void *value) {
|
void operator()(const void *value) {
|
||||||
if (spec_.type_ && spec_.type_ != 'p')
|
if (spec_.type_ && spec_.type_ != 'p')
|
||||||
report_unknown_type(spec_.type_, "pointer");
|
report_unknown_type(spec_.type_, "pointer");
|
||||||
|
@ -563,13 +563,9 @@ TEST(UtilTest, StringArg) {
|
|||||||
char *str = str_data;
|
char *str = str_data;
|
||||||
const char *cstr = str;
|
const char *cstr = str;
|
||||||
CHECK_ARG_(char, cstr, str);
|
CHECK_ARG_(char, cstr, str);
|
||||||
CHECK_ARG_(wchar_t, cstr, str);
|
|
||||||
CHECK_ARG(cstr);
|
|
||||||
|
|
||||||
string_view sref(str);
|
string_view sref(str);
|
||||||
CHECK_ARG_(char, sref, std::string(str));
|
CHECK_ARG_(char, sref, std::string(str));
|
||||||
CHECK_ARG_(wchar_t, sref, std::string(str));
|
|
||||||
CHECK_ARG(sref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UtilTest, WStringArg) {
|
TEST(UtilTest, WStringArg) {
|
||||||
@ -578,8 +574,8 @@ TEST(UtilTest, WStringArg) {
|
|||||||
const wchar_t *cstr = str;
|
const wchar_t *cstr = str;
|
||||||
|
|
||||||
fmt::wstring_view sref(str);
|
fmt::wstring_view sref(str);
|
||||||
CHECK_ARG_(wchar_t, sref, str);
|
CHECK_ARG_(wchar_t, cstr, str);
|
||||||
CHECK_ARG_(wchar_t, sref, cstr);
|
CHECK_ARG_(wchar_t, cstr, cstr);
|
||||||
CHECK_ARG_(wchar_t, sref, std::wstring(str));
|
CHECK_ARG_(wchar_t, sref, std::wstring(str));
|
||||||
CHECK_ARG_(wchar_t, sref, fmt::wstring_view(str));
|
CHECK_ARG_(wchar_t, sref, fmt::wstring_view(str));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user