From 8484b5dc8aa1ca7338e4b8ee209017dcf527681e Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 11 Jun 2018 19:20:51 +0300 Subject: [PATCH] Add parameter type checks to printf style functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc supports type checks for printf parameters which can catch some hard to reproduce bugs. Possible bugs happen when the parameter value is intepreted differently to the variable value. Example warnings follow ../library/LuaWrapper.cpp:1011:86: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=] ../plugins/follow.cpp:159:35: warning: format not a string literal and no format arguments [-Wformat-security] --- library/Hooks-windows.cpp | 2 +- library/include/ColorText.h | 8 ++++---- library/include/Core.h | 4 ++-- library/include/Export.h | 11 +++++++++++ library/include/MiscUtils.h | 4 ++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/library/Hooks-windows.cpp b/library/Hooks-windows.cpp index 3d925bc27..8f77865e8 100644 --- a/library/Hooks-windows.cpp +++ b/library/Hooks-windows.cpp @@ -463,7 +463,7 @@ DFhackCExport char * SDL_GetError(void) } static void (*_SDL_SetError)(const char *fmt, ...) = 0; -DFhackCExport void SDL_SetError(const char *fmt, ...) +DFhackCExport void SDL_SetError(const char *fmt, ...) Wformat(printf,1,2) { char buf[1024]; va_list args; diff --git a/library/include/ColorText.h b/library/include/ColorText.h index 006fa119d..f6da7ac88 100644 --- a/library/include/ColorText.h +++ b/library/include/ColorText.h @@ -106,12 +106,12 @@ namespace DFHack virtual ~color_ostream(); /// Print a formatted string, like printf - void print(const char *format, ...); - void vprint(const char *format, va_list args); + void print(const char *format, ...) Wformat(printf,2,3); + void vprint(const char *format, va_list args) Wformat(printf,2,0); /// Print a formatted string, like printf, in red - void printerr(const char *format, ...); - void vprinterr(const char *format, va_list args); + void printerr(const char *format, ...) Wformat(printf,2,3); + void vprinterr(const char *format, va_list args) Wformat(printf,2,0); /// Get color color_value color() { return cur_color; } diff --git a/library/include/Core.h b/library/include/Core.h index fa65645a1..7d51e7613 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -191,8 +191,8 @@ namespace DFHack DFHack::VersionInfo * vinfo; DFHack::Windows::df_window * screen_window; - static void print(const char *format, ...); - static void printerr(const char *format, ...); + static void print(const char *format, ...) Wformat(printf,1,2); + static void printerr(const char *format, ...) Wformat(printf,1,2); PluginManager *getPluginManager() { return plug_mgr; } diff --git a/library/include/Export.h b/library/include/Export.h index 87d38b45f..9e2a78d4b 100644 --- a/library/include/Export.h +++ b/library/include/Export.h @@ -58,3 +58,14 @@ distribution. #define DFhackCExport extern "C" __declspec(dllexport) #define DFhackDataExport extern "C" __declspec(dllexport) #endif + +// Make gcc warn if types and format string don't match for printf +#ifdef __GNUC__ + //! Tell GCC about format functions to allow parameter strict type checks + //! \param type The type of function can be printf, scanf, strftime or strfmon + //! \param fmtstr One based position index for format parameter + //! \param vararg One based position index for the first checked parameter + #define Wformat(type, fmtstr, vararg) __attribute__ ((format (type, fmtstr, vararg))) +#else + #define Wformat(type, fmtstr, vararg) +#endif diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 378b7a728..488949681 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -354,8 +354,8 @@ DFHACK_EXPORT int random_int(int max); */ DFHACK_EXPORT uint64_t GetTimeMs64(); -DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...); -DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args); +DFHACK_EXPORT std::string stl_sprintf(const char *fmt, ...) Wformat(printf,1,2); +DFHACK_EXPORT std::string stl_vsprintf(const char *fmt, va_list args) Wformat(printf,1,0); // Conversion between CP437 and UTF-8 DFHACK_EXPORT std::string UTF2DF(const std::string &in);