diff --git a/src/console.cpp b/src/console.cpp index 29bab2f740..2274da64fe 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -137,7 +137,7 @@ void CDECL IConsolePrintF(TextColour colour_code, const char *format, ...) char buf[ICON_MAX_STREAMSIZE]; va_start(va, format); - vsnprintf(buf, sizeof(buf), format, va); + vseprintf(buf, lastof(buf), format, va); va_end(va); IConsolePrint(colour_code, buf); diff --git a/src/debug.cpp b/src/debug.cpp index ad99dc38d8..16eecadad0 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -163,7 +163,7 @@ void CDECL debug(const char *dbg, const char *format, ...) va_list va; va_start(va, format); - vsnprintf(buf, lengthof(buf), format, va); + vseprintf(buf, lastof(buf), format, va); va_end(va); debug_print(dbg, buf); diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 83dc9a6044..30e6304950 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -31,7 +31,7 @@ void CDECL strgen_warning(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); DEBUG(script, 0, "%s:%d: warning: %s", _file, _cur_line, buf); _warnings++; @@ -42,7 +42,7 @@ void CDECL strgen_error(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); DEBUG(script, 0, "%s:%d: error: %s", _file, _cur_line, buf); _errors++; @@ -53,7 +53,7 @@ void NORETURN CDECL strgen_fatal(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); DEBUG(script, 0, "%s:%d: FATAL: %s", _file, _cur_line, buf); throw std::exception(); diff --git a/src/misc/str.hpp b/src/misc/str.hpp index b109b4e82f..b982913fc2 100644 --- a/src/misc/str.hpp +++ b/src/misc/str.hpp @@ -100,7 +100,7 @@ struct CStrA : public CBlobT int err = 0; for (;;) { char *buf = MakeFreeSpace(addSize); - ret = vsnprintf(buf, base::GetReserve(), format, args); + ret = vseprintf(buf, buf + base::GetReserve() - 1, format, args); if (ret >= (int)base::GetReserve()) { /* Greater return than given count means needed buffer size. */ addSize = ret + 1; diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index f8a0867f34..b1a5dcb55d 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -86,7 +86,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *m va_list va; va_start(va, message); - vsnprintf(buf, lengthof(buf), message, va); + vseprintf(buf, lastof(buf), message, va); va_end(va); Utf8TrimString(buf, DRAW_STRING_BUFFER); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 90fd24bf14..079c121621 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -377,7 +377,7 @@ void CDECL grfmsg(int severity, const char *str, ...) va_list va; va_start(va, str); - vsnprintf(buf, sizeof(buf), str, va); + vseprintf(buf, lastof(buf), str, va); va_end(va); DEBUG(grf, severity, "[%s:%d] %s", _cur.grfconfig->filename, _cur.nfo_line, buf); diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index d3b5ddd164..6d5312514c 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -400,7 +400,7 @@ struct NewGRFInspectWindow : Window { va_list va; va_start(va, format); - vsnprintf(buf, lengthof(buf), format, va); + vseprintf(buf, lastof(buf), format, va); va_end(va); offset -= this->vscroll->GetPosition(); diff --git a/src/openttd.cpp b/src/openttd.cpp index 4dcd49fbfc..57e32489de 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -93,7 +93,7 @@ void CDECL usererror(const char *s, ...) char buf[512]; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); ShowOSErrorBox(buf, false); @@ -113,7 +113,7 @@ void CDECL error(const char *s, ...) char buf[512]; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); ShowOSErrorBox(buf, true); @@ -132,7 +132,7 @@ void CDECL ShowInfoF(const char *str, ...) va_list va; char buf[1024]; va_start(va, str); - vsnprintf(buf, lengthof(buf), str, va); + vseprintf(buf, lastof(buf), str, va); va_end(va); ShowInfo(buf); } diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index 9ead866e7f..99e5ae1c09 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -21,9 +21,10 @@ /* Due to the different characters for Squirrel, the scsnprintf might be a simple * snprint which triggers the safeguard. But it isn't always a simple snprintf. - * Likewise for scstrcat. */ + * Likewise for scvsnprintf and scstrcat. */ #include "../safeguards.h" #undef snprintf +#undef vsnprintf #undef strcat void Squirrel::CompileError(HSQUIRRELVM vm, const SQChar *desc, const SQChar *source, SQInteger line, SQInteger column) diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp index 9f8cc10501..dd92e2627b 100644 --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -42,7 +42,7 @@ void NORETURN CDECL error(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); fprintf(stderr, "FATAL: %s\n", buf); exit(1); diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 2fb89f0885..4cd2454f4e 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -53,7 +53,7 @@ void CDECL strgen_warning(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); fprintf(stderr, LINE_NUM_FMT("warning"), _file, _cur_line, buf); _warnings++; @@ -64,7 +64,7 @@ void CDECL strgen_error(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); fprintf(stderr, LINE_NUM_FMT("error"), _file, _cur_line, buf); _errors++; @@ -75,7 +75,7 @@ void NORETURN CDECL strgen_fatal(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); fprintf(stderr, LINE_NUM_FMT("FATAL"), _file, _cur_line, buf); #ifdef _MSC_VER @@ -89,7 +89,7 @@ void NORETURN CDECL error(const char *s, ...) char buf[1024]; va_list va; va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); + vseprintf(buf, lastof(buf), s, va); va_end(va); fprintf(stderr, LINE_NUM_FMT("FATAL"), _file, _cur_line, buf); #ifdef _MSC_VER diff --git a/src/string.cpp b/src/string.cpp index 8a95d7b6fe..63288e4316 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -32,7 +32,10 @@ #include "gfx_func.h" #endif /* WITH_ICU */ +/* The function vsnprintf is used internally to perform the required formatting + * tasks. As such this one must be allowed, and makes sure it's terminated. */ #include "safeguards.h" +#undef vsnprintf /** * Safer implementation of vsnprintf; same as vsnprintf except: @@ -44,7 +47,7 @@ * @param ap the list of arguments for the format * @return the number of added characters */ -static int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) +int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap) { ptrdiff_t diff = last - str; if (diff < 0) return 0; diff --git a/src/string_func.h b/src/string_func.h index 8354d67cde..474340a69f 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -34,6 +34,7 @@ char *strecpy(char *dst, const char *src, const char *last); char *stredup(const char *src, const char *last = NULL); int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FORMAT(3, 4); +int CDECL vseprintf(char *str, const char *last, const char *format, va_list ap); char *CDECL str_fmt(const char *str, ...) WARN_FORMAT(1, 2); diff --git a/src/textbuf.cpp b/src/textbuf.cpp index c11e3c1bf1..116d60ba87 100644 --- a/src/textbuf.cpp +++ b/src/textbuf.cpp @@ -419,7 +419,7 @@ void Textbuf::Print(const char *format, ...) { va_list va; va_start(va, format); - vsnprintf(this->buf, this->max_bytes, format, va); + vseprintf(this->buf, &this->buf[this->max_bytes - 1], format, va); va_end(va); this->UpdateSize(); }