From ba01a5db32db389e785129f7f52a315911c8056e Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 19 Nov 2017 10:28:01 -0800 Subject: [PATCH] Disallow formatting of multibyte strings into a wide buffer (#606) --- include/fmt/format.h | 50 +++++++++++++++++++------------------------- test/util-test.cc | 4 ---- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 2ea0a86bc1c9..4697f432f9fe 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1112,7 +1112,7 @@ enum type { INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR, // followed by floating-point types. DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, - CSTRING, STRING, TSTRING, POINTER, CUSTOM + CSTRING, STRING, POINTER, CUSTOM }; constexpr bool is_integral(type t) { @@ -1189,10 +1189,10 @@ template <> constexpr type get_type() { return CSTRING; } template <> constexpr type get_type() { return CSTRING; } template <> constexpr type get_type() { return STRING; } template <> constexpr type get_type() { return STRING; } -template <> constexpr type get_type() { return TSTRING; } -template <> constexpr type get_type() { return TSTRING; } -template <> constexpr type get_type() { return TSTRING; } -template <> constexpr type get_type() { return TSTRING; } +template <> constexpr type get_type() { return CSTRING; } +template <> constexpr type get_type() { return CSTRING; } +template <> constexpr type get_type() { return STRING; } +template <> constexpr type get_type() { return STRING; } template <> constexpr type get_type() { return POINTER; } template <> constexpr type get_type() { return POINTER; } template <> constexpr type get_type() { return POINTER; } @@ -1225,10 +1225,9 @@ class value { double double_value; long double long_double_value; const void *pointer; - string_value string; + string_value string; string_value sstring; string_value ustring; - string_value tstring; custom_value custom; }; @@ -1271,18 +1270,16 @@ class value { } #endif - value(char *s) { set(string.value, s); } - value(const char *s) { set(string.value, s); } - value(signed char *s) { set(sstring.value, s); } - value(const signed char *s) { set(sstring.value, s); } - value(unsigned char *s) { set(ustring.value, s); } - value(const unsigned char *s) { set(ustring.value, s); } - value(string_view s) { set_string(s); } - value(const std::string &s) { set_string(s); } - value(wstring_view s) { set_wstring(s); } - value(const std::wstring &s) { set_wstring(s); } - value(wchar_t *s) { set_wstring(wstring_view(s)); } - value(const wchar_t *s) { set_wstring(wstring_view(s)); } + // Formatting of wide strings into a narrow buffer and multibyte strings + // into a wide buffer is disallowed (https://github.com/fmtlib/fmt/pull/606). + value(char_type *s) { set(string.value, s); } + value(const char_type *s) { set(string.value, s); } + value(signed char *s) { set_cstring(sstring.value, s); } + value(const signed char *s) { set_cstring(sstring.value, s); } + value(unsigned char *s) { set_cstring(ustring.value, s); } + value(const unsigned char *s) { set_cstring(ustring.value, s); } + value(basic_string_view s) { set_string(s); } + value(const std::basic_string &s) { set_string(s); } // Formatting of arbitrary pointers is disallowed. If you want to output a // pointer cast it to "void *" or "const void *". In particular, this forbids @@ -1338,12 +1335,11 @@ class value { string.size = value.size(); } - template - void set_wstring(const T &value) { - require_wchar(); - static_assert(get_type() == TSTRING, "invalid type"); - tstring.value = value.data(); - tstring.size = value.size(); + template + constexpr void set_cstring(T &field, const U *str) { + static_assert(std::is_same::value, + "incompatible string types"); + set(field, str); } // Formats an argument of a custom type, such as a user-defined class. @@ -1439,10 +1435,8 @@ constexpr typename std::result_of::type case internal::CSTRING: return vis(arg.value_.string.value); case internal::STRING: - return vis(string_view(arg.value_.string.value, arg.value_.string.size)); - case internal::TSTRING: return vis(basic_string_view( - arg.value_.tstring.value, arg.value_.tstring.size)); + arg.value_.string.value, arg.value_.string.size)); case internal::POINTER: return vis(arg.value_.pointer); case internal::CUSTOM: diff --git a/test/util-test.cc b/test/util-test.cc index ce9205bf3bb7..74608952568f 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -563,13 +563,9 @@ TEST(UtilTest, StringArg) { char *str = str_data; const char *cstr = str; CHECK_ARG_(char, cstr, str); - CHECK_ARG_(wchar_t, cstr, str); - CHECK_ARG(cstr); string_view sref(str); CHECK_ARG_(char, sref, std::string(str)); - CHECK_ARG_(wchar_t, sref, std::string(str)); - CHECK_ARG(sref); } TEST(UtilTest, WStringArg) {