From 9537cfd3f8264700619f58d15741829489e1099e Mon Sep 17 00:00:00 2001 From: nOOb3167 Date: Sun, 22 Jul 2018 21:56:06 +0200 Subject: [PATCH] Add a MSVC / Windows compatible snprintf function (#7353) Use sizeof where applicable for mt_snprintf --- src/game.cpp | 3 ++- src/gui/guiConfirmRegistration.cpp | 6 ++++-- src/gui/profilergraph.cpp | 5 +++-- src/guiscalingfilter.cpp | 3 ++- src/map.cpp | 6 +++--- src/mapblock.cpp | 3 ++- src/porting.cpp | 24 ++++++++++++++++++++++++ src/porting.h | 2 ++ src/script/common/c_internal.cpp | 3 ++- src/script/cpp_api/s_base.cpp | 2 +- src/serverenvironment.cpp | 5 +++-- src/unittest/test.cpp | 5 +++-- src/unittest/test_connection.cpp | 5 +++-- 13 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 6e2583412..005241495 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -53,6 +53,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" // Needed for determining pointing to nodes #include "nodemetadata.h" #include "particles.h" +#include "porting.h" #include "profiler.h" #include "quicktune_shortcutter.h" #include "raycast.h" @@ -4028,7 +4029,7 @@ void Game::showPauseMenu() char control_text_buf[600]; - snprintf(control_text_buf, ARRLEN(control_text_buf), control_text_template.c_str(), + porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(), GET_KEY_NAME(keymap_forward), GET_KEY_NAME(keymap_backward), GET_KEY_NAME(keymap_left), diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index fea9f5cda..7f5aec264 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "intlGUIEditBox.h" +#include "porting.h" #include "gettext.h" @@ -96,8 +97,9 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize) "Join to confirm account creation or click Cancel to " "abort."); char info_text_buf[1024]; - snprintf(info_text_buf, sizeof(info_text_buf), info_text_template.c_str(), - address.c_str(), m_playername.c_str()); + porting::mt_snprintf(info_text_buf, sizeof(info_text_buf), + info_text_template.c_str(), address.c_str(), + m_playername.c_str()); wchar_t *info_text_buf_wide = utf8_to_wide_c(info_text_buf); gui::IGUIEditBox *e = new gui::intlGUIEditBox(info_text_buf_wide, true, diff --git a/src/gui/profilergraph.cpp b/src/gui/profilergraph.cpp index 740dfa35c..b29285e2f 100644 --- a/src/gui/profilergraph.cpp +++ b/src/gui/profilergraph.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "porting.h" #include "profilergraph.h" #include "util/string.h" @@ -95,12 +96,12 @@ void ProfilerGraph::draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver, s32 texth = 15; char buf[10]; - snprintf(buf, 10, "%.3g", show_max); + porting::mt_snprintf(buf, sizeof(buf), "%.3g", show_max); font->draw(utf8_to_wide(buf).c_str(), core::rect(textx, y - graphh, textx2, y - graphh + texth), meta.color); - snprintf(buf, 10, "%.3g", show_min); + porting::mt_snprintf(buf, sizeof(buf), "%.3g", show_min); font->draw(utf8_to_wide(buf).c_str(), core::rect(textx, y - texth, textx2, y), meta.color); font->draw(utf8_to_wide(id).c_str(), diff --git a/src/guiscalingfilter.cpp b/src/guiscalingfilter.cpp index dc6219b60..3b4377da5 100644 --- a/src/guiscalingfilter.cpp +++ b/src/guiscalingfilter.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiscalingfilter.h" #include "imagefilters.h" +#include "porting.h" #include "settings.h" #include "util/numeric.h" #include @@ -78,7 +79,7 @@ video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver, // Calculate scaled texture name. char rectstr[200]; - snprintf(rectstr, sizeof(rectstr), "%d:%d:%d:%d:%d:%d", + porting::mt_snprintf(rectstr, sizeof(rectstr), "%d:%d:%d:%d:%d:%d", srcrect.UpperLeftCorner.X, srcrect.UpperLeftCorner.Y, srcrect.getWidth(), diff --git a/src/map.cpp b/src/map.cpp index 35bdc3e9c..801027ae2 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1727,13 +1727,13 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout) switch(layout) { case 1: - snprintf(cc, 9, "%.4x%.4x", + porting::mt_snprintf(cc, sizeof(cc), "%.4x%.4x", (unsigned int) pos.X & 0xffff, (unsigned int) pos.Y & 0xffff); return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc; case 2: - snprintf(cc, 9, (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(), + porting::mt_snprintf(cc, sizeof(cc), (std::string("%.3x") + DIR_DELIM + "%.3x").c_str(), (unsigned int) pos.X & 0xfff, (unsigned int) pos.Y & 0xfff); @@ -1791,7 +1791,7 @@ v3s16 ServerMap::getBlockPos(const std::string §ordir, const std::string &bl std::string ServerMap::getBlockFilename(v3s16 p) { char cc[5]; - snprintf(cc, 5, "%.4x", (unsigned int)p.Y&0xffff); + porting::mt_snprintf(cc, sizeof(cc), "%.4x", (unsigned int)p.Y&0xffff); return cc; } diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 54cb2df0e..cf815d16b 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef SERVER #include "mapblock_mesh.h" #endif +#include "porting.h" #include "util/string.h" #include "util/serialize.h" #include "util/basic_macros.h" @@ -797,7 +798,7 @@ std::string analyze_block(MapBlock *block) v3s16 p = block->getPos(); char spos[25]; - snprintf(spos, sizeof(spos), "(%2d,%2d,%2d), ", p.X, p.Y, p.Z); + porting::mt_snprintf(spos, sizeof(spos), "(%2d,%2d,%2d), ", p.X, p.Y, p.Z); desc<getModified()) diff --git a/src/porting.cpp b/src/porting.cpp index 240ee0af0..302e6989a 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -50,6 +50,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "settings.h" #include +#include +#include namespace porting { @@ -661,6 +663,28 @@ void attachOrCreateConsole() #endif } +int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) +{ + // https://msdn.microsoft.com/en-us/library/bt7tawza.aspx + // Many of the MSVC / Windows printf-style functions do not support positional + // arguments (eg. "%1$s"). We just forward the call to vsnprintf for sane + // platforms, but defer to _vsprintf_p on MSVC / Windows. + // https://github.com/FFmpeg/FFmpeg/blob/5ae9fa13f5ac640bec113120d540f70971aa635d/compat/msvcrt/snprintf.c#L46 + // _vsprintf_p has to be shimmed with _vscprintf_p on -1 (for an example see + // above FFmpeg link). + va_list args; + va_start(args, fmt); +#ifndef _MSC_VER + int c = vsnprintf(buf, buf_size, fmt, args); +#else // _MSC_VER + int c = _vsprintf_p(buf, buf_size, fmt, args); + if (c == -1) + c = _vscprintf_p(fmt, args); +#endif // _MSC_VER + va_end(args); + return c; +} + // Load performance counter frequency only once at startup #ifdef _WIN32 diff --git a/src/porting.h b/src/porting.h index 1f9f066fb..4d30a5970 100644 --- a/src/porting.h +++ b/src/porting.h @@ -327,6 +327,8 @@ bool secure_rand_fill_buf(void *buf, size_t len); // This attaches to the parents process console, or creates a new one if it doesnt exist. void attachOrCreateConsole(); + +int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...); } // namespace porting #ifdef __ANDROID__ diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 9a24b0e78..be9691ef4 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_internal.h" #include "debug.h" #include "log.h" +#include "porting.h" #include "settings.h" std::string script_get_backtrace(lua_State *L) @@ -82,7 +83,7 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f err_descr = ""; char buf[256]; - snprintf(buf, sizeof(buf), "%s error from mod '%s' in callback %s(): ", + porting::mt_snprintf(buf, sizeof(buf), "%s error from mod '%s' in callback %s(): ", err_type, mod, fxn); std::string err_msg(buf); diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 293c774b0..d98359d20 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -293,7 +293,7 @@ void ScriptApiBase::stackDump(std::ostream &o) break; case LUA_TNUMBER: /* numbers */ { char buf[10]; - snprintf(buf, 10, "%lf", lua_tonumber(m_luastack, i)); + porting::mt_snprintf(buf, sizeof(buf), "%lf", lua_tonumber(m_luastack, i)); o << buf; break; } diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 08870589e..7d7eb4c08 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodemetadata.h" #include "gamedef.h" #include "map.h" +#include "porting.h" #include "profiler.h" #include "raycast.h" #include "remoteplayer.h" @@ -1860,9 +1861,9 @@ static void print_hexdump(std::ostream &o, const std::string &data) int i = i0 + di; char buf[4]; if(di 20)