Mercurial > hg > bitcoin
changeset 3494:aa323efdf02c draft
Add printf-style warnings to strprintf() and OutputDebugStringF()
This finds about ~150 potential problems with format characters on a 64 bit build.
author | Wladimir J. van der Laan <laanwj@gmail.com> |
---|---|
date | Sun, 09 Sep 2012 14:43:06 +0200 |
parents | 7cbbd4be0230 |
children | 89393e88d1f4 |
files | src/util.cpp src/util.h |
diffstat | 2 files changed, 42 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/util.cpp +++ b/src/util.cpp @@ -274,7 +274,7 @@ return ret; } -string vstrprintf(const std::string &format, va_list ap) +string vstrprintf(const char *format, va_list ap) { char buffer[50000]; char* p = buffer; @@ -284,7 +284,7 @@ { va_list arg_ptr; va_copy(arg_ptr, ap); - ret = _vsnprintf(p, limit, format.c_str(), arg_ptr); + ret = _vsnprintf(p, limit, format, arg_ptr); va_end(arg_ptr); if (ret >= 0 && ret < limit) break; @@ -301,11 +301,20 @@ return str; } +string real_strprintf(const char *format, int dummy, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, dummy); + string str = vstrprintf(format, arg_ptr); + va_end(arg_ptr); + return str; +} + string real_strprintf(const std::string &format, int dummy, ...) { va_list arg_ptr; va_start(arg_ptr, dummy); - string str = vstrprintf(format, arg_ptr); + string str = vstrprintf(format.c_str(), arg_ptr); va_end(arg_ptr); return str; }
--- a/src/util.h +++ b/src/util.h @@ -41,7 +41,6 @@ #define UBEGIN(a) ((unsigned char*)&(a)) #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) -#define printf OutputDebugStringF #ifndef PRI64d #if defined(_MSC_VER) || defined(__MSVCRT__) @@ -94,6 +93,15 @@ } #endif +/* This GNU C extension enables the compiler to check the format string against the parameters provided. + * X is the number of the "format string" parameter, and Y is the number of the first variadic parameter. + * Parameters count from 1. + */ +#ifdef __GNUC__ +#define ATTR_WARN_PRINTF(X,Y) __attribute__((format(printf,X,Y))) +#else +#define ATTR_WARN_PRINTF(X,Y) +#endif @@ -121,16 +129,32 @@ void RandAddSeed(); void RandAddSeedPerfmon(); -int OutputDebugStringF(const char* pszFormat, ...); +int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...); int my_snprintf(char* buffer, size_t limit, const char* format, ...); -/* It is not allowed to use va_start with a pass-by-reference argument. - (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a - macro to keep similar semantics. +/* + Rationale for the real_strprintf / strprintf construction: + It is not allowed to use va_start with a pass-by-reference argument. + (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a + macro to keep similar semantics. */ + +/** Overload strprintf for char*, so that GCC format type warnings can be given */ +std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...); +/** Overload strprintf for std::string, to be able to use it with _ (translation). + * This will not support GCC format type warnings (-Wformat) so be careful. + */ std::string real_strprintf(const std::string &format, int dummy, ...); #define strprintf(format, ...) real_strprintf(format, 0, __VA_ARGS__) -std::string vstrprintf(const std::string &format, va_list ap); +std::string vstrprintf(const char *format, va_list ap); + +/* Redefine printf so that it directs output to debug.log + * + * Do this *after* defining the other printf-like functions, because otherwise the + * __attribute__((format(printf,X,Y))) gets expanded to __attribute__((format(OutputDebugStringF,X,Y))) + * which confuses gcc. + */ +#define printf OutputDebugStringF bool error(const char *format, ...); void LogException(std::exception* pex, const char* pszThread);