Add a MSVC / Windows compatible snprintf function (#7353)
authornOOb3167 <nOOb3167@gmail.com>
Sun, 22 Jul 2018 19:56:06 +0000 (21:56 +0200)
committerSmallJoker <SmallJoker@users.noreply.github.com>
Sun, 22 Jul 2018 19:56:06 +0000 (21:56 +0200)
Use sizeof where applicable for mt_snprintf

13 files changed:
src/game.cpp
src/gui/guiConfirmRegistration.cpp
src/gui/profilergraph.cpp
src/guiscalingfilter.cpp
src/map.cpp
src/mapblock.cpp
src/porting.cpp
src/porting.h
src/script/common/c_internal.cpp
src/script/cpp_api/s_base.cpp
src/serverenvironment.cpp
src/unittest/test.cpp
src/unittest/test_connection.cpp

index 6e25834129d08bf8ea25b937d01e152bed8ddedb..005241495f69926bdaa21d2644cbd3ecf6e71263 100644 (file)
@@ -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),
index fea9f5cda1371e577dd9cf4c9d7508aee52f38a7..7f5aec2641b20909732a11f8458f8ac4786a1366 100644 (file)
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <IGUIStaticText.h>
 #include <IGUIFont.h>
 #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,
index 740dfa35c95b05927ad1f502a5d38a19cd01aae6..b29285e2f8dc2872465b2e211720dabdc732c7b7 100644 (file)
@@ -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<s32>(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<s32>(textx, y - texth, textx2, y), meta.color);
                font->draw(utf8_to_wide(id).c_str(),
index dc6219b60ba9b611f80d60786424283942a116b1..3b4377da53bab32b08070424fcfe51849ba8c870 100644 (file)
@@ -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 <cstdio>
@@ -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(),
index 35bdc3e9c95d511d47afbe371c9c53e74714e161..801027ae2e6a2f9df84e15eb1ff51899e47e0fa8 100644 (file)
@@ -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 &sectordir, 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;
 }
 
index 54cb2df0e4432c06ed20f1b9d9740a2e2cc1ca80..cf815d16b6ff9bd8f7620fe36d524733a5f69b33 100644 (file)
@@ -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<<spos;
 
        switch(block->getModified())
index 240ee0af0ceff4d545d4f35cc9fc51055f2db720..302e6989a1ca075caad8e858f241340e9ef60cb1 100644 (file)
@@ -50,6 +50,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/string.h"
 #include "settings.h"
 #include <list>
+#include <cstdarg>
+#include <cstdio>
 
 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
 
index 1f9f066fb6b7cb49c39a20e456f664874380a0d9..4d30a5970f2ffd20b66088d60d48a4b2c1fac89d 100644 (file)
@@ -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__
index 9a24b0e787c139a28229cf67d645517325a41d25..be9691ef44c42523c8017e98dc75a5f155667fb7 100644 (file)
@@ -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 = "<no description>";
 
        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);
index 293c774b0cb84f483949499fd07015c26025f902..d98359d20d4dec1d1e0ead3c557997bb327fe1bc 100644 (file)
@@ -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;
                        }
index 08870589ea86f3b4aee9a04d6bcdd8de3197714f..7d7eb4c088ee4cd387e044cab85dbb2f547a1ca5 100644 (file)
@@ -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<thislinelength)
-                               snprintf(buf, 4, "%.2x ", data[i]);
+                               porting::mt_snprintf(buf, sizeof(buf), "%.2x ", data[i]);
                        else
-                               snprintf(buf, 4, "   ");
+                               porting::mt_snprintf(buf, sizeof(buf), "   ");
                        o<<buf;
                }
                o<<" ";
index 547c3fd07ea9f0fd030d1e5ed1e526444885a8f5..3ac8ffb193885e971856ee03f9709b5698ec0212 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "modchannels.h"
 #include "content/mods.h"
 #include "util/numeric.h"
+#include "porting.h"
 
 content_t t_CONTENT_STONE;
 content_t t_CONTENT_GRASS;
@@ -323,7 +324,7 @@ std::string TestBase::getTestTempDirectory()
                return m_test_dir;
 
        char buf[32];
-       snprintf(buf, sizeof(buf), "%08X", myrand());
+       porting::mt_snprintf(buf, sizeof(buf), "%08X", myrand());
 
        m_test_dir = fs::TempPath() + DIR_DELIM "mttest_" + buf;
        if (!fs::CreateDir(m_test_dir))
@@ -335,7 +336,7 @@ std::string TestBase::getTestTempDirectory()
 std::string TestBase::getTestTempFile()
 {
        char buf[32];
-       snprintf(buf, sizeof(buf), "%08X", myrand());
+       porting::mt_snprintf(buf, sizeof(buf), "%08X", myrand());
 
        return getTestTempDirectory() + DIR_DELIM + buf + ".tmp";
 }
index 8217c403e4170134632b596c5739bfc71116977d..c5e4085e1de4c380ac1137c6928d204239286815 100644 (file)
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "test.h"
 
 #include "log.h"
+#include "porting.h"
 #include "settings.h"
 #include "util/serialize.h"
 #include "network/connection.h"
@@ -280,7 +281,7 @@ void TestConnection::testConnectSendReceive()
                        if (i % 2 == 0)
                                infostream << " ";
                        char buf[10];
-                       snprintf(buf, 10, "%.2X",
+                       porting::mt_snprintf(buf, sizeof(buf), "%.2X",
                                ((int)((const char *)pkt.getU8Ptr(0))[i]) & 0xff);
                        infostream<<buf;
                }
@@ -323,7 +324,7 @@ void TestConnection::testConnectSendReceive()
                        if (i % 2 == 0)
                                infostream << " ";
                        char buf[10];
-                       snprintf(buf, 10, "%.2X", ((int)(recvdata[i])) & 0xff);
+                       porting::mt_snprintf(buf, sizeof(buf), "%.2X", ((int)(recvdata[i])) & 0xff);
                        infostream << buf;
                }
                if (size > 20)