Add printf-style warnings to strprintf() and OutputDebugStringF()
This finds about ~150 potential problems with format characters on a 64 bit build.
This commit is contained in:
parent
eabc8f2c81
commit
b0a90fbb0c
2 changed files with 42 additions and 9 deletions
15
src/util.cpp
15
src/util.cpp
|
@ -274,7 +274,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
|
|||
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 @@ string vstrprintf(const std::string &format, va_list ap)
|
|||
{
|
||||
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,7 +301,7 @@ string vstrprintf(const std::string &format, va_list ap)
|
|||
return str;
|
||||
}
|
||||
|
||||
string real_strprintf(const std::string &format, int dummy, ...)
|
||||
string real_strprintf(const char *format, int dummy, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
va_start(arg_ptr, dummy);
|
||||
|
@ -310,6 +310,15 @@ string real_strprintf(const std::string &format, int dummy, ...)
|
|||
return str;
|
||||
}
|
||||
|
||||
string real_strprintf(const std::string &format, int dummy, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
va_start(arg_ptr, dummy);
|
||||
string str = vstrprintf(format.c_str(), arg_ptr);
|
||||
va_end(arg_ptr);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool error(const char *format, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
|
|
32
src/util.h
32
src/util.h
|
@ -41,7 +41,6 @@ static const int64 CENT = 1000000;
|
|||
#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 @@ inline void Sleep(int64 n)
|
|||
}
|
||||
#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 @@ extern bool fReopenDebugLog;
|
|||
|
||||
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.
|
||||
/*
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue