shithub: choc

Download patch

ref: 8eb3200286d523379295143ce3f44d77ce036d4b
parent: 565a1f08566520147a5abff5744dbcc256e5030c
author: Simon Howard <fraggle@gmail.com>
date: Tue Apr 1 16:43:45 EDT 2014

Replace all snprintf() calls with M_snprintf().

The Windows API has an _snprintf function that is not the same as
Unix's snprintf(): if the string is truncated then no trailing NUL
character is appended. This makes the function unsafe. Define a
replacement/wrapper called M_snprintf that works the same but always
appends a trailing NUL, for safety on Windows and other OSes that
behave like this.

Do the same thing for vsnprintf(), and update HACKING to list
snprintf/vsnprintf as forbidden functions. This fixes #375;
thanks to Quasar for pointing out the different behavior of these
functions.

--- a/HACKING
+++ b/HACKING
@@ -122,7 +122,10 @@
     Unsafe function       Safer alternative
     ---------------------------------------------
     gets()                fgets(.., stdin)
-    sprintf               snprintf()
+    sprintf               M_snprintf()
+    snprintf              M_snprintf()
+    vsprintf              M_vsnprintf()
+    vsnprintf             M_vsnprintf()
     strcpy()              M_StringCopy()
     strncpy()             M_StringCopy()
     strcat()              M_StringConcat()
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -351,14 +351,14 @@
 
     len = strlen(install_path) + strlen(STEAM_BFG_GUS_PATCHES) + 20;
     patch_path = malloc(len);
-    snprintf(patch_path, len, "%s\\%s\\ACBASS.PAT",
-             install_path, STEAM_BFG_GUS_PATCHES);
+    M_snprintf(patch_path, len, "%s\\%s\\ACBASS.PAT",
+               install_path, STEAM_BFG_GUS_PATCHES);
 
     // Does acbass.pat exist? If so, then set gus_patch_path.
     if (M_FileExists(patch_path))
     {
-        snprintf(patch_path, len, "%s\\%s",
-                 install_path, STEAM_BFG_GUS_PATCHES);
+        M_snprintf(patch_path, len, "%s\\%s",
+                   install_path, STEAM_BFG_GUS_PATCHES);
         M_SetVariable("gus_patch_path", patch_path);
     }
 
--- a/src/deh_str.c
+++ b/src/deh_str.c
@@ -31,6 +31,7 @@
 
 #include "doomtype.h"
 #include "deh_str.h"
+#include "m_misc.h"
 
 #include "z_zone.h"
 
@@ -401,7 +402,7 @@
 
     va_start(args, fmt);
 
-    vsnprintf(buffer, len, repl, args);
+    M_vsnprintf(buffer, len, repl, args);
 
     va_end(args);
 }
--- a/src/doom/am_map.c
+++ b/src/doom/am_map.c
@@ -38,6 +38,7 @@
 
 #include "m_cheat.h"
 #include "m_controls.h"
+#include "m_misc.h"
 #include "i_system.h"
 
 // Needs access to LFB.
@@ -689,8 +690,8 @@
         }
         else if (key == key_map_mark)
         {
-            snprintf(buffer, sizeof(buffer), "%s %d",
-                     DEH_String(AMSTR_MARKEDSPOT), markpointnum);
+            M_snprintf(buffer, sizeof(buffer), "%s %d",
+                       DEH_String(AMSTR_MARKEDSPOT), markpointnum);
             plr->message = buffer;
             AM_addMark();
         }
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -384,7 +384,7 @@
     {
         char buf[12];
 
-        snprintf(buf, sizeof(buf), "chatmacro%i", i);
+        M_snprintf(buf, sizeof(buf), "chatmacro%i", i);
         M_BindVariable(buf, &chat_macros[i]);
     }
 }
@@ -669,8 +669,8 @@
             gamename_size = strlen(deh_sub) + 10;
             gamename = Z_Malloc(gamename_size, PU_STATIC, 0);
             version = G_VanillaVersionCode();
-            snprintf(gamename, gamename_size, deh_sub,
-                     version / 100, version % 100);
+            M_snprintf(gamename, gamename_size, deh_sub,
+                       version / 100, version % 100);
 
             while (gamename[0] != '\0' && isspace(gamename[0]))
             {
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -915,8 +915,8 @@
             {
                 static char turbomessage[80];
                 extern char *player_names[4];
-                snprintf(turbomessage, sizeof(turbomessage),
-                         "%s is turbo!", player_names[i]);
+                M_snprintf(turbomessage, sizeof(turbomessage),
+                           "%s is turbo!", player_names[i]);
                 players[consoleplayer].message = turbomessage;
                 turbodetected[i] = false;
             }
@@ -1949,7 +1949,7 @@
     usergame = false;
     demoname_size = strlen(name) + 5;
     demoname = Z_Malloc(demoname_size, PU_STATIC, NULL);
-    snprintf(demoname, demoname_size, "%s.lmp", name);
+    M_snprintf(demoname, demoname_size, "%s.lmp", name);
     maxsize = 0x20000;
 
     //!
@@ -2076,8 +2076,8 @@
     }
     else
     {
-        snprintf(resultbuf, sizeof(resultbuf),
-                 "%i.%i (unknown)", version / 100, version % 100);
+        M_snprintf(resultbuf, sizeof(resultbuf),
+                   "%i.%i (unknown)", version / 100, version % 100);
         return resultbuf;
     }
 }
--- a/src/doom/hu_stuff.c
+++ b/src/doom/hu_stuff.c
@@ -627,8 +627,8 @@
 		// static unsigned char buf[20]; // DEBUG
 		HU_queueChatChar(c);
 		
-		// snprintf(buf, sizeof(buf), "KEY: %d => %d", ev->data1, c);
-		//      plr->message = buf;
+		// M_snprintf(buf, sizeof(buf), "KEY: %d => %d", ev->data1, c);
+		//        plr->message = buf;
 	    }
 	    if (c == KEY_ENTER)
 	    {
--- a/src/doom/p_saveg.c
+++ b/src/doom/p_saveg.c
@@ -79,7 +79,7 @@
     }
 
     DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
-    snprintf(filename, filename_size, "%s%s", savegamedir, basename);
+    M_snprintf(filename, filename_size, "%s%s", savegamedir, basename);
 
     return filename;
 }
@@ -1363,7 +1363,7 @@
         saveg_write8(0);
 
     memset(name, 0, sizeof(name));
-    snprintf(name, sizeof(name), "version %i", G_VanillaVersionCode());
+    M_snprintf(name, sizeof(name), "version %i", G_VanillaVersionCode());
 
     for (i=0; i<VERSIONSIZE; ++i)
         saveg_write8(name[i]);
@@ -1400,7 +1400,7 @@
         read_vcheck[i] = saveg_read8();
 
     memset(vcheck, 0, sizeof(vcheck));
-    snprintf(vcheck, sizeof(vcheck), "version %i", G_VanillaVersionCode());
+    M_snprintf(vcheck, sizeof(vcheck), "version %i", G_VanillaVersionCode());
     if (strcmp(read_vcheck, vcheck) != 0)
 	return false;				// bad version 
 
--- a/src/doom/s_sound.c
+++ b/src/doom/s_sound.c
@@ -38,6 +38,7 @@
 #include "sounds.h"
 #include "s_sound.h"
 
+#include "m_misc.h"
 #include "m_random.h"
 #include "m_argv.h"
 
@@ -638,7 +639,7 @@
     // get lumpnum if neccessary
     if (!music->lumpnum)
     {
-        snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name));
+        M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name));
         music->lumpnum = W_GetNumForName(namebuf);
     }
 
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -33,6 +33,7 @@
 #include "i_system.h"
 #include "i_video.h"
 #include "z_zone.h"
+#include "m_misc.h"
 #include "m_random.h"
 #include "w_wad.h"
 
@@ -598,10 +599,10 @@
       else if (cht_CheckCheat(&cheat_mypos, ev->data2))
       {
         static char buf[ST_MSGWIDTH];
-        snprintf(buf, sizeof(buf), "ang=0x%x;x,y=(0x%x,0x%x)",
-                 players[consoleplayer].mo->angle,
-                 players[consoleplayer].mo->x,
-                 players[consoleplayer].mo->y);
+        M_snprintf(buf, sizeof(buf), "ang=0x%x;x,y=(0x%x,0x%x)",
+                   players[consoleplayer].mo->angle,
+                   players[consoleplayer].mo->x,
+                   players[consoleplayer].mo->y);
         plyr->message = buf;
       }
     }
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -35,10 +35,6 @@
 
 #ifdef _WIN32
 
-#define snprintf _snprintf
-#if _MSC_VER < 1400 /* not needed for Visual Studio 2008 */
-#define vsnprintf _vsnprintf
-#endif
 #define strcasecmp stricmp
 #define strncasecmp strnicmp
 
--- a/src/heretic/am_map.c
+++ b/src/heretic/am_map.c
@@ -411,7 +411,7 @@
     //char namebuf[9];
 /*  for (i=0;i<10;i++)
   {
-    snprintf(namebuf, sizeof(namebuf), "AMMNUM%d", i);
+    M_snprintf(namebuf, sizeof(namebuf), "AMMNUM%d", i);
     marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
   }*/
     maplump = W_CacheLumpName(DEH_String("AUTOPAGE"), PU_STATIC);
@@ -603,8 +603,8 @@
         }
         else if (key == key_map_mark)
         {
-            snprintf(buffer, sizeof(buffer), "%s %d",
-                     AMSTR_MARKEDSPOT, markpointnum);
+            M_snprintf(buffer, sizeof(buffer), "%s %d",
+                       AMSTR_MARKEDSPOT, markpointnum);
             plr->message = buffer;
             AM_addMark();
         }
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -247,7 +247,7 @@
     if (M_CheckParm("-debugfile"))
     {
         char filename[20];
-        snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer);
+        M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer);
         debugfile = fopen(filename, "w");
     }
     I_GraphicsCheckCommandLine();
@@ -776,7 +776,7 @@
     {
         char buf[12];
 
-        snprintf(buf, sizeof(buf), "chatmacro%i", i);
+        M_snprintf(buf, sizeof(buf), "chatmacro%i", i);
         M_BindVariable(buf, &chat_macros[i]);
     }
 }
--- a/src/heretic/f_finale.c
+++ b/src/heretic/f_finale.c
@@ -405,7 +405,7 @@
         laststage = stage;
     }
 
-    snprintf(name, sizeof(name), "END%i", stage);
+    M_snprintf(name, sizeof(name), "END%i", stage);
     V_DrawPatch((SCREENWIDTH - 13 * 8) / 2, (SCREENHEIGHT - 8 * 8) / 2,
                 W_CacheLumpName(name, PU_CACHE));
 }
--- a/src/heretic/i_sound.c
+++ b/src/heretic/i_sound.c
@@ -211,8 +211,8 @@
         return 0;
     if (sound->link)
         sound = sound->link;
-//  snprintf(namebuf, sizeof(namebuf), "d%c%s",
-//           snd_prefixen[snd_SfxDevice], sound->name);
+//  M_snprintf(namebuf, sizeof(namebuf), "d%c%s",
+//             snd_prefixen[snd_SfxDevice], sound->name);
     return W_GetNumForName(sound->name);
 
 }
@@ -320,15 +320,15 @@
     {
         if (debugmode)
         {
-            snprintf(tmp, sizeof(tmp), "cfg p=0x%x, i=%d, d=%d\n",
-                     snd_SBport, snd_SBirq, snd_SBdma);
+            M_snprintf(tmp, sizeof(tmp), "cfg p=0x%x, i=%d, d=%d\n",
+                       snd_SBport, snd_SBirq, snd_SBdma);
             tprintf(tmp, 0);
         }
         if (SB_Detect(&snd_SBport, &snd_SBirq, &snd_SBdma, 0))
         {
-            snprintf(tmp, sizeof(tmp),
-                     "SB isn't responding at p=0x%x, i=%d, d=%d\n",
-                     snd_SBport, snd_SBirq, snd_SBdma);
+            M_snprintf(tmp, sizeof(tmp),
+                       "SB isn't responding at p=0x%x, i=%d, d=%d\n",
+                       snd_SBport, snd_SBirq, snd_SBdma);
             tprintf(tmp, 0);
         }
         else
@@ -336,8 +336,8 @@
 
         if (debugmode)
         {
-            snprintf(tmp, sizeof(tmp), "SB_Detect returned p=0x%x,i=%d,d=%d\n",
-                     snd_SBport, snd_SBirq, snd_SBdma);
+            M_snprintf(tmp, sizeof(tmp), "SB_Detect returned p=0x%x,i=%d,d=%d\n",
+                       snd_SBport, snd_SBirq, snd_SBdma);
             tprintf(tmp, 0);
         }
     }
@@ -354,14 +354,14 @@
     {
         if (debugmode)
         {
-            snprintf(tmp, sizeof(tmp), "cfg p=0x%x\n", snd_Mport);
+            M_snprintf(tmp, sizeof(tmp), "cfg p=0x%x\n", snd_Mport);
             tprintf(tmp, 0);
         }
 
         if (MPU_Detect(&snd_Mport, &i))
         {
-            snprintf(tmp, sizeof(tmp),
-                     "The MPU-401 isn't reponding @ p=0x%x.\n", snd_Mport);
+            M_snprintf(tmp, sizeof(tmp),
+                       "The MPU-401 isn't reponding @ p=0x%x.\n", snd_Mport);
             tprintf(tmp, 0);
         }
         else
@@ -399,11 +399,11 @@
 
     if (debugmode)
     {
-        snprintf(tmp, sizeof(tmp), "  Music device #%d & dmxCode=%d",
-                 snd_MusicDevice, dmxCodes[snd_MusicDevice]);
+        M_snprintf(tmp, sizeof(tmp), "  Music device #%d & dmxCode=%d",
+                   snd_MusicDevice, dmxCodes[snd_MusicDevice]);
         tprintf(tmp, 0);
-        snprintf(tmp, sizeof(tmp),  "  Sfx device #%d & dmxCode=%d\n",
-                 snd_SfxDevice, dmxCodes[snd_SfxDevice]);
+        M_snprintf(tmp, sizeof(tmp),  "  Sfx device #%d & dmxCode=%d\n",
+                   snd_SfxDevice, dmxCodes[snd_SfxDevice]);
         tprintf(tmp, 0);
     }
 
@@ -414,7 +414,7 @@
 
     if (debugmode)
     {
-        snprintf(tmp, sizeof(tmp), "  DMX_Init() returned %d", rc);
+        M_snprintf(tmp, sizeof(tmp), "  DMX_Init() returned %d", rc);
         tprintf(tmp, 0);
     }
 
--- a/src/heretic/p_saveg.c
+++ b/src/heretic/p_saveg.c
@@ -55,8 +55,8 @@
 
     filename_len = strlen(savegamedir) + strlen(SAVEGAMENAME) + 8;
     filename = malloc(filename_len);
-    snprintf(filename, filename_len,
-             "%s" SAVEGAMENAME "%d.hsg", savegamedir, slot);
+    M_snprintf(filename, filename_len,
+               "%s" SAVEGAMENAME "%d.hsg", savegamedir, slot);
 
     return filename;
 }
--- a/src/heretic/sb_bar.c
+++ b/src/heretic/sb_bar.c
@@ -484,20 +484,20 @@
             MN_DrTextA(DEH_String("------"), xPos[0], y);
             continue;
         }
-        snprintf(text, sizeof(text), "%s", c->name);
+        M_snprintf(text, sizeof(text), "%s", c->name);
         M_ForceUppercase(text);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->type);
+        M_snprintf(text, sizeof(text), "%d", c->mo->type);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS);
+        M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS);
+        M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->id);
+        M_snprintf(text, sizeof(text), "%d", c->id);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->priority);
+        M_snprintf(text, sizeof(text), "%d", c->priority);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->distance);
+        M_snprintf(text, sizeof(text), "%d", c->distance);
         MN_DrTextA(text, xPos[x++], y);
     }
     UpdateState |= I_FULLSCRN;
--- a/src/hexen/am_map.c
+++ b/src/hexen/am_map.c
@@ -29,6 +29,7 @@
 #include "i_video.h"
 #include "i_swap.h"
 #include "m_controls.h"
+#include "m_misc.h"
 #include "p_local.h"
 #include "am_map.h"
 #include "am_data.h"
@@ -1474,8 +1475,8 @@
         else
         {
             MN_DrTextA(PlayerColorText[order[i]], 8, yPosition);
-            snprintf(textBuffer, sizeof(textBuffer),
-                     "%d", fragCount[order[i]]);
+            M_snprintf(textBuffer, sizeof(textBuffer),
+                       "%d", fragCount[order[i]]);
             MN_DrTextA(textBuffer, 80, yPosition);
             yPosition += 10;
         }
@@ -1509,8 +1510,8 @@
     worldTimer -= minutes * 60;
     seconds = worldTimer;
 
-    snprintf(timeBuffer, sizeof(timeBuffer),
-             "%.2d : %.2d : %.2d", hours, minutes, seconds);
+    M_snprintf(timeBuffer, sizeof(timeBuffer),
+               "%.2d : %.2d : %.2d", hours, minutes, seconds);
     MN_DrTextA(timeBuffer, 240, 8);
 
     if (days)
@@ -1517,11 +1518,11 @@
     {
         if (days == 1)
         {
-            snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAY", days);
+            M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAY", days);
         }
         else
         {
-            snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAYS", days);
+            M_snprintf(dayBuffer, sizeof(dayBuffer), "%.2d DAYS", days);
         }
         MN_DrTextA(dayBuffer, 240, 20);
         if (days >= 5)
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -172,7 +172,7 @@
     {
         char buf[12];
 
-        snprintf(buf, sizeof(buf), "chatmacro%i", i);
+        M_snprintf(buf, sizeof(buf), "chatmacro%i", i);
         M_BindVariable(buf, &chat_macros[i]);
     }
 }
@@ -190,7 +190,7 @@
     if (!strcmp(SavePath, ""))
     {
         SavePath = malloc(10);
-	snprintf(SavePath, 10, "hexndata%c", DIR_SEPARATOR);
+	M_snprintf(SavePath, 10, "hexndata%c", DIR_SEPARATOR);
     }
 }
 
@@ -632,7 +632,7 @@
     if (M_CheckParm("-debugfile"))
     {
         char filename[20];
-        snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer);
+        M_snprintf(filename, sizeof(filename), "debug%i.txt", consoleplayer);
         debugfile = fopen(filename, "w");
     }
     I_SetWindowTitle("Hexen");
--- a/src/hexen/in_lude.c
+++ b/src/hexen/in_lude.c
@@ -28,6 +28,7 @@
 #include "s_sound.h"
 #include "i_system.h"
 #include "i_video.h"
+#include "m_misc.h"
 #include "p_local.h"
 #include "v_video.h"
 
@@ -537,8 +538,8 @@
 
     if (!(val < -9 && wrapThresh < 1000))
     {
-        snprintf(buff, sizeof(buff), "%d",
-                 val >= wrapThresh ? val % wrapThresh : val);
+        M_snprintf(buff, sizeof(buff), "%d",
+                   val >= wrapThresh ? val % wrapThresh : val);
     }
     MN_DrTextA(buff, x - MN_TextAWidth(buff) / 2, y);
 }
@@ -555,8 +556,8 @@
 
     if (!(val < -9 && wrapThresh < 1000))
     {
-        snprintf(buff, sizeof(buff), "%d",
-                 val >= wrapThresh ? val % wrapThresh : val);
+        M_snprintf(buff, sizeof(buff), "%d",
+                   val >= wrapThresh ? val % wrapThresh : val);
     }
     MN_DrTextAYellow(buff, x - MN_TextAWidth(buff) / 2, y);
 }
--- a/src/hexen/mn_menu.c
+++ b/src/hexen/mn_menu.c
@@ -685,7 +685,7 @@
     char name[100];
     char versionText[HXS_VERSION_TEXT_LENGTH];
 
-    snprintf(name, sizeof(name), "%shex%d.hxs", SavePath, slot);
+    M_snprintf(name, sizeof(name), "%shex%d.hxs", SavePath, slot);
 
     fp = fopen(name, "rb");
 
--- a/src/hexen/p_acs.c
+++ b/src/hexen/p_acs.c
@@ -443,8 +443,8 @@
     if (infoIndex == -1)
     {                           // Script not found
         //I_Error("P_StartACS: Unknown script number %d", number);
-        snprintf(ErrorMsg, sizeof(ErrorMsg),
-                 "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number);
+        M_snprintf(ErrorMsg, sizeof(ErrorMsg),
+                   "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number);
         P_SetMessage(&players[consoleplayer], ErrorMsg, true);
     }
     statePtr = &ACSInfo[infoIndex].state;
@@ -540,8 +540,8 @@
     {
         if (!(mo->player->keys & (1 << (lock - 1))))
         {
-            snprintf(LockedBuffer, sizeof(LockedBuffer),
-                     "YOU NEED THE %s\n", TextKeyMessages[lock - 1]);
+            M_snprintf(LockedBuffer, sizeof(LockedBuffer),
+                       "YOU NEED THE %s\n", TextKeyMessages[lock - 1]);
             P_SetMessage(mo->player, LockedBuffer, true);
             S_StartSound(mo, SFX_DOOR_LOCKED);
             return false;
@@ -1692,7 +1692,7 @@
 {
     char tempStr[16];
 
-    snprintf(tempStr, sizeof(tempStr), "%d", Pop());
+    M_snprintf(tempStr, sizeof(tempStr), "%d", Pop());
     M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer));
     return SCRIPT_CONTINUE;
 }
--- a/src/hexen/p_setup.c
+++ b/src/hexen/p_setup.c
@@ -700,7 +700,7 @@
     P_InitThinkers();
     leveltime = 0;
 
-    snprintf(lumpname, sizeof(lumpname), "MAP%02d", map);
+    M_snprintf(lumpname, sizeof(lumpname), "MAP%02d", map);
     lumpnum = W_GetNumForName(lumpname);
     //
     // Begin processing map lumps
--- a/src/hexen/p_spec.c
+++ b/src/hexen/p_spec.c
@@ -27,6 +27,7 @@
 
 #include "h2def.h"
 #include "i_system.h"
+#include "m_misc.h"
 #include "p_local.h"
 #include "s_sound.h"
 
@@ -428,8 +429,8 @@
     }
     if (!(mo->player->keys & (1 << (lock - 1))))
     {
-        snprintf(LockedBuffer, sizeof(LockedBuffer),
-                 "YOU NEED THE %s\n", TextKeyMessages[lock - 1]);
+        M_snprintf(LockedBuffer, sizeof(LockedBuffer),
+                   "YOU NEED THE %s\n", TextKeyMessages[lock - 1]);
         P_SetMessage(mo->player, LockedBuffer, true);
         S_StartSound(mo, SFX_DOOR_LOCKED);
         return false;
--- a/src/hexen/sb_bar.c
+++ b/src/hexen/sb_bar.c
@@ -640,20 +640,20 @@
             MN_DrTextA("------", xPos[0], y);
             continue;
         }
-        snprintf(text, sizeof(text), "%s", c->name);
+        M_snprintf(text, sizeof(text), "%s", c->name);
         M_ForceUppercase(text);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->type);
+        M_snprintf(text, sizeof(text), "%d", c->mo->type);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS);
+        M_snprintf(text, sizeof(text), "%d", c->mo->x >> FRACBITS);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS);
+        M_snprintf(text, sizeof(text), "%d", c->mo->y >> FRACBITS);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", (int) c->id);
+        M_snprintf(text, sizeof(text), "%d", (int) c->id);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->priority);
+        M_snprintf(text, sizeof(text), "%d", c->priority);
         MN_DrTextA(text, xPos[x++], y);
-        snprintf(text, sizeof(text), "%d", c->distance);
+        M_snprintf(text, sizeof(text), "%d", c->distance);
         MN_DrTextA(text, xPos[x++], y);
     }
     UpdateState |= I_FULLSCRN;
@@ -1738,7 +1738,7 @@
         P_SetMessage(player, TXT_CHEATBADINPUT, true);
         return;
     }
-    snprintf(mapName, sizeof(mapName), "MAP%02d", map);
+    M_snprintf(mapName, sizeof(mapName), "MAP%02d", map);
     if (W_CheckNumForName(mapName) == -1)
     {                       // Can't find
         P_SetMessage(player, TXT_CHEATNOMAP, true);
@@ -1769,7 +1769,7 @@
     char buffer[80];
 
     count = P_Massacre();
-    snprintf(buffer, sizeof(buffer), "%d MONSTERS KILLED\n", count);
+    M_snprintf(buffer, sizeof(buffer), "%d MONSTERS KILLED\n", count);
     P_SetMessage(player, buffer, true);
 }
 
@@ -1857,12 +1857,12 @@
 static void CheatDebugFunc(player_t * player, Cheat_t * cheat)
 {
     char textBuffer[50];
-    snprintf(textBuffer, sizeof(textBuffer),
-             "MAP %d (%d)  X:%5d  Y:%5d  Z:%5d",
-             P_GetMapWarpTrans(gamemap),
-             gamemap,
-             player->mo->x >> FRACBITS,
-             player->mo->y >> FRACBITS, player->mo->z >> FRACBITS);
+    M_snprintf(textBuffer, sizeof(textBuffer),
+               "MAP %d (%d)  X:%5d  Y:%5d  Z:%5d",
+               P_GetMapWarpTrans(gamemap),
+               gamemap,
+               player->mo->x >> FRACBITS,
+               player->mo->y >> FRACBITS, player->mo->z >> FRACBITS);
     P_SetMessage(player, textBuffer, true);
 }
 
@@ -1897,8 +1897,8 @@
 
     if (P_StartACS(script, 0, script_args, player->mo, NULL, 0))
     {
-        snprintf(textBuffer, sizeof(textBuffer),
-                 "RUNNING SCRIPT %.2d", script);
+        M_snprintf(textBuffer, sizeof(textBuffer),
+                   "RUNNING SCRIPT %.2d", script);
         P_SetMessage(player, textBuffer, true);
     }
 }
@@ -1930,8 +1930,8 @@
         P_SetMessage(player, "ERROR INITIALIZING CD", true);
     }
 
-    snprintf(buffer, sizeof(buffer), "ENTER DESIRED CD TRACK (%.2d - %.2d):\n",
-            I_CDMusFirstTrack(), I_CDMusLastTrack());
+    M_snprintf(buffer, sizeof(buffer), "ENTER DESIRED CD TRACK (%.2d - %.2d):\n",
+               I_CDMusFirstTrack(), I_CDMusLastTrack());
     P_SetMessage(player, buffer, true);
 }
 
@@ -1968,14 +1968,14 @@
 
     if (!S_StartCustomCDTrack(track))
     {
-        snprintf(buffer, sizeof(buffer),
-                 "ERROR WHILE TRYING TO PLAY CD TRACK: %.2d\n", track);
+        M_snprintf(buffer, sizeof(buffer),
+                   "ERROR WHILE TRYING TO PLAY CD TRACK: %.2d\n", track);
         P_SetMessage(player, buffer, true);
     }
     else
     {
         // No error encountered while attempting to play the track
-        snprintf(buffer, sizeof(buffer), "PLAYING TRACK: %.2d\n", track);
+        M_snprintf(buffer, sizeof(buffer), "PLAYING TRACK: %.2d\n", track);
         P_SetMessage(player, buffer, true);
     }
 }
--- a/src/hexen/sc_man.c
+++ b/src/hexen/sc_man.c
@@ -88,7 +88,7 @@
 
     if (sc_FileScripts == true)
     {
-        snprintf(fileName, sizeof(fileName), "%s%s.txt", sc_ScriptsDir, name);
+        M_snprintf(fileName, sizeof(fileName), "%s%s.txt", sc_ScriptsDir, name);
         SC_OpenFile(fileName);
     }
     else
--- a/src/hexen/sv_save.c
+++ b/src/hexen/sv_save.c
@@ -1940,7 +1940,7 @@
     unsigned int i;
 
     // Open the output file
-    snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath);
+    M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath);
     OpenStreamOut(fileName);
 
     // Write game save description
@@ -2000,7 +2000,7 @@
     SavingPlayers = savePlayers;
 
     // Open the output file
-    snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
+    M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
     OpenStreamOut(fileName);
 
     // Place a header marker
@@ -2048,7 +2048,7 @@
     }
 
     // Create the name
-    snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath);
+    M_snprintf(fileName, sizeof(fileName), "%shex6.hxs", SavePath);
 
     // Load the file
     M_ReadFile(fileName, &SaveBuffer);
@@ -2192,7 +2192,7 @@
     TargetPlayerAddrs = NULL;
 
     gamemap = map;
-    snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
+    M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
     if (!deathmatch && ExistingFile(fileName))
     {                           // Unarchive map
         SV_LoadMap();
@@ -2342,7 +2342,7 @@
 {
     char fileName[100];
 
-    snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, REBORN_SLOT);
+    M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, REBORN_SLOT);
     return ExistingFile(fileName);
 }
 
@@ -2363,7 +2363,7 @@
     RemoveAllThinkers();
 
     // Create the name
-    snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
+    M_snprintf(fileName, sizeof(fileName), "%shex6%02d.hxs", SavePath, gamemap);
 
     // Load the file
     M_ReadFile(fileName, &SaveBuffer);
@@ -3204,11 +3204,11 @@
 
     for (i = 0; i < MAX_MAPS; i++)
     {
-        snprintf(fileName, sizeof(fileName),
-                 "%shex%d%02d.hxs", SavePath, slot, i);
+        M_snprintf(fileName, sizeof(fileName),
+                   "%shex%d%02d.hxs", SavePath, slot, i);
         remove(fileName);
     }
-    snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, slot);
+    M_snprintf(fileName, sizeof(fileName), "%shex%d.hxs", SavePath, slot);
     remove(fileName);
 }
 
@@ -3228,21 +3228,21 @@
 
     for (i = 0; i < MAX_MAPS; i++)
     {
-        snprintf(sourceName, sizeof(sourceName),
-                 "%shex%d%02d.hxs", SavePath, sourceSlot, i);
+        M_snprintf(sourceName, sizeof(sourceName),
+                   "%shex%d%02d.hxs", SavePath, sourceSlot, i);
         if (ExistingFile(sourceName))
         {
-            snprintf(destName, sizeof(destName),
-                     "%shex%d%02d.hxs", SavePath, destSlot, i);
+            M_snprintf(destName, sizeof(destName),
+                       "%shex%d%02d.hxs", SavePath, destSlot, i);
             CopyFile(sourceName, destName);
         }
     }
-    snprintf(sourceName, sizeof(sourceName),
-             "%shex%d.hxs", SavePath, sourceSlot);
+    M_snprintf(sourceName, sizeof(sourceName),
+               "%shex%d.hxs", SavePath, sourceSlot);
     if (ExistingFile(sourceName))
     {
-        snprintf(destName, sizeof(destName),
-                 "%shex%d.hxs", SavePath, destSlot);
+        M_snprintf(destName, sizeof(destName),
+                   "%shex%d.hxs", SavePath, destSlot);
         CopyFile(sourceName, destName);
     }
 }
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -1527,11 +1527,11 @@
 
     if (num_tracks == 0)
     {
-        snprintf(result, result_len, "No OPL track!");
+        M_snprintf(result, result_len, "No OPL track!");
         return;
     }
 
-    snprintf(result, result_len, "Tracks:\n");
+    M_snprintf(result, result_len, "Tracks:\n");
     lines = 1;
 
     for (i = 0; i < NumActiveChannels(); ++i)
@@ -1543,18 +1543,18 @@
 
         instr_num = tracks[0].channels[i].instrument - main_instrs;
 
-        snprintf(tmp, sizeof(tmp),
-                "chan %i: %c i#%i (%s)\n",
-                i,
-                ChannelInUse(&tracks[0].channels[i]) ? '\'' : ' ',
-                instr_num + 1,
-                main_instr_names[instr_num]);
+        M_snprintf(tmp, sizeof(tmp),
+                   "chan %i: %c i#%i (%s)\n",
+                   i,
+                   ChannelInUse(&tracks[0].channels[i]) ? '\'' : ' ',
+                   instr_num + 1,
+                   main_instr_names[instr_num]);
         M_StringConcat(result, tmp, result_len);
 
         ++lines;
     }
 
-    snprintf(tmp, sizeof(tmp), "\nLast percussion:\n");
+    M_snprintf(tmp, sizeof(tmp), "\nLast percussion:\n");
     M_StringConcat(result, tmp, result_len);
     lines += 2;
 
@@ -1566,11 +1566,11 @@
             break;
         }
 
-        snprintf(tmp, sizeof(tmp),
-                 "%cp#%i (%s)\n",
-                 i == 0 ? '\'' : ' ',
-                 last_perc[i],
-                 percussion_names[last_perc[i] - 35]);
+        M_snprintf(tmp, sizeof(tmp),
+                   "%cp#%i (%s)\n",
+                   i == 0 ? '\'' : ' ',
+                   last_perc[i],
+                   percussion_names[last_perc[i] - 35]);
         M_StringConcat(result, tmp, result_len);
         ++lines;
 
--- a/src/i_pcsound.c
+++ b/src/i_pcsound.c
@@ -253,7 +253,7 @@
 
     if (use_sfx_prefix)
     {
-        snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String(sfx->name));
+        M_snprintf(namebuf, sizeof(namebuf), "dp%s", DEH_String(sfx->name));
     }
     else
     {
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -705,8 +705,8 @@
     {
         char filename[16];
 
-        snprintf(filename, sizeof(filename), "%s.wav",
-                 DEH_String(S_sfx[sound].name));
+        M_snprintf(filename, sizeof(filename), "%s.wav",
+                   DEH_String(S_sfx[sound].name));
         WriteWAV(filename, sound_chunks[sound].abuf,
                  sound_chunks[sound].alen, mixer_freq);
     }
@@ -733,7 +733,7 @@
 
     if (use_sfx_prefix)
     {
-        snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name));
+        M_snprintf(buf, buf_len, "ds%s", DEH_String(sfx->name));
     }
     else
     {
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -318,7 +318,7 @@
 
         va_start(argptr, error);
         memset(msgbuf, 0, sizeof(msgbuf));
-        vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr);
+        M_vsnprintf(msgbuf, sizeof(msgbuf), error, argptr);
         va_end(argptr);
 
         MultiByteToWideChar(CP_ACP, 0,
@@ -338,7 +338,7 @@
 
         va_start(argptr, error);
         memset(msgbuf, 0, sizeof(msgbuf));
-        vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr);
+        M_vsnprintf(msgbuf, sizeof(msgbuf), error, argptr);
         va_end(argptr);
 
 	// The CoreFoundation message box wraps text lines, so replace
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -1820,7 +1820,7 @@
     }
     else if (sscanf(window_position, "%i,%i", &x, &y) == 2)
     {
-        snprintf(buf, sizeof(buf), "SDL_VIDEO_WINDOW_POS=%i,%i", x, y);
+        M_snprintf(buf, sizeof(buf), "SDL_VIDEO_WINDOW_POS=%i,%i", x, y);
         putenv(buf);
     }
 }
@@ -1990,7 +1990,7 @@
         int winid;
 
         sscanf(env, "0x%x", &winid);
-        snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%i", winid);
+        M_snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%i", winid);
 
         putenv(winenv);
     }
--- a/src/m_controls.c
+++ b/src/m_controls.c
@@ -28,6 +28,7 @@
 #include "doomkeys.h"
 
 #include "m_config.h"
+#include "m_misc.h"
 
 //
 // Keyboard controls
@@ -385,7 +386,7 @@
 
     for (i=0; i<num_players; ++i)
     {
-        snprintf(name, sizeof(name), "key_multi_msgplayer%i", i + 1);
+        M_snprintf(name, sizeof(name), "key_multi_msgplayer%i", i + 1);
         M_BindVariable(name, &key_multi_msgplayer[i]);
     }
 }
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -449,6 +449,39 @@
     return result;
 }
 
+// On Windows, vsnprintf() is _vsnprintf().
+#ifdef _WIN32
+#if _MSC_VER < 1400 /* not needed for Visual Studio 2008 */
+#define vsnprintf _vsnprintf
+#endif
+#endif
+
+// Safe, portable vsnprintf().
+int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args)
+{
+    if (buf_len < 1)
+    {
+        return 0;
+    }
+
+    // Windows (and other OSes?) has a vsnprintf() that doesn't always
+    // append a trailing \0. So we must do it, and write into a buffer
+    // that is one byte shorter; otherwise this function is unsafe.
+    buf[buf_len - 1] = '\0';
+    return vsnprintf(buf, buf_len - 1, s, args);
+}
+
+// Safe, portable snprintf().
+int M_snprintf(char *buf, size_t buf_len, const char *s, ...)
+{
+    va_list args;
+    int result;
+    va_start(args, s);
+    result = M_vsnprintf(buf, buf_len, s, args);
+    va_end(args);
+    return result;
+}
+
 #ifdef _WIN32
 
 char *M_OEMToUTF8(const char *oem)
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -28,8 +28,8 @@
 #ifndef __M_MISC__
 #define __M_MISC__
 
-
 #include <stdio.h>
+#include <stdarg.h>
 
 #include "doomtype.h"
 
@@ -50,6 +50,8 @@
 char *M_StringJoin(const char *s, ...);
 boolean M_StringStartsWith(const char *s, const char *prefix);
 boolean M_StringEndsWith(const char *s, const char *suffix);
+int M_vsnprintf(char *buf, size_t buf_len, const char *s, va_list args);
+int M_snprintf(char *buf, size_t buf_len, const char *s, ...);
 char *M_OEMToUTF8(const char *ansi);
 
 #endif
--- a/src/net_gui.c
+++ b/src/net_gui.c
@@ -34,6 +34,7 @@
 #include "i_system.h"
 #include "i_timer.h"
 #include "i_video.h"
+#include "m_misc.h"
 
 #include "net_client.h"
 #include "net_gui.h"
@@ -101,7 +102,7 @@
 
     for (i = 0; i < net_client_wait_data.max_players; ++i)
     {
-        snprintf(buf, sizeof(buf), " %i. ", i + 1);
+        M_snprintf(buf, sizeof(buf), " %i. ", i + 1);
         TXT_AddWidget(table, TXT_NewLabel(buf));
         player_labels[i] = TXT_NewLabel("");
         ip_labels[i] = TXT_NewLabel("");
@@ -164,8 +165,8 @@
 
     if (net_client_wait_data.num_drones > 0)
     {
-        snprintf(buf, sizeof(buf), " (+%i observer clients)",
-                 net_client_wait_data.num_drones);
+        M_snprintf(buf, sizeof(buf), " (+%i observer clients)",
+                   net_client_wait_data.num_drones);
         TXT_SetLabel(drone_label, buf);
     }
     else
--- a/src/net_loop.c
+++ b/src/net_loop.c
@@ -28,6 +28,7 @@
 
 #include "doomtype.h"
 #include "i_system.h"
+#include "m_misc.h"
 #include "net_defs.h"
 #include "net_loop.h"
 #include "net_packet.h"
@@ -128,7 +129,7 @@
 
 static void NET_CL_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)
 {
-    snprintf(buffer, buffer_len, "local server");
+    M_snprintf(buffer, buffer_len, "local server");
 }
 
 static void NET_CL_FreeAddress(net_addr_t *addr)
@@ -204,7 +205,7 @@
 
 static void NET_SV_AddrToString(net_addr_t *addr, char *buffer, int buffer_len)
 {
-    snprintf(buffer, buffer_len, "local client");
+    M_snprintf(buffer, buffer_len, "local client");
 }
 
 static void NET_SV_FreeAddress(net_addr_t *addr)
--- a/src/net_sdl.c
+++ b/src/net_sdl.c
@@ -30,6 +30,7 @@
 #include "doomtype.h"
 #include "i_system.h"
 #include "m_argv.h"
+#include "m_misc.h"
 #include "net_defs.h"
 #include "net_io.h"
 #include "net_packet.h"
@@ -312,12 +313,12 @@
 
     ip = (IPaddress *) addr->handle;
     
-    snprintf(buffer, buffer_len, 
-             "%i.%i.%i.%i",
-             ip->host & 0xff,
-             (ip->host >> 8) & 0xff,
-             (ip->host >> 16) & 0xff,
-             (ip->host >> 24) & 0xff);
+    M_snprintf(buffer, buffer_len, 
+               "%i.%i.%i.%i",
+               ip->host & 0xff,
+               (ip->host >> 8) & 0xff,
+               (ip->host >> 16) & 0xff,
+               (ip->host >> 24) & 0xff);
 }
 
 net_addr_t *NET_SDL_ResolveAddress(char *address)
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -200,7 +200,7 @@
     net_packet_t *packet;
 
     va_start(args, s);
-    vsnprintf(buf, sizeof(buf), s, args);
+    M_vsnprintf(buf, sizeof(buf), s, args);
     va_end(args);
     
     packet = NET_Conn_NewReliable(&client->connection, 
@@ -218,7 +218,7 @@
     int i;
 
     va_start(args, s);
-    vsnprintf(buf, sizeof(buf), s, args);
+    M_vsnprintf(buf, sizeof(buf), s, args);
     va_end(args);
     
     for (i=0; i<MAXNETNODES; ++i)
--- a/src/setup/txt_mouseinput.c
+++ b/src/setup/txt_mouseinput.c
@@ -90,7 +90,7 @@
             M_StringCopy(buf, "MID", buf_len);
             break;
         default:
-            snprintf(buf, buf_len, "BUTTON #%i", button + 1);
+            M_snprintf(buf, buf_len, "BUTTON #%i", button + 1);
             break;
     }
 }
--- a/src/strife/am_map.c
+++ b/src/strife/am_map.c
@@ -32,6 +32,7 @@
 #include "z_zone.h"
 #include "doomkeys.h"
 #include "doomdef.h"
+#include "m_misc.h"
 #include "st_stuff.h"
 #include "p_local.h"
 #include "w_wad.h"
@@ -670,8 +671,8 @@
         }
         else if (key == key_map_mark)
         {
-            snprintf(buffer, sizeof(buffer),
-                     "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
+            M_snprintf(buffer, sizeof(buffer),
+                       "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
             plr->message = buffer;
             AM_addMark();
         }
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -461,7 +461,7 @@
     {
         char buf[12];
 
-        snprintf(buf, sizeof(buf), "chatmacro%i", i);
+        M_snprintf(buf, sizeof(buf), "chatmacro%i", i);
         M_BindVariable(buf, &chat_macros[i]);
     }
 }
@@ -792,8 +792,8 @@
 
             gamename_size = strlen(deh_sub) + 10;
             gamename = Z_Malloc(gamename_size, PU_STATIC, 0);
-            snprintf(gamename, gamename_size, deh_sub,
-                     STRIFE_VERSION / 100, STRIFE_VERSION % 100);
+            M_snprintf(gamename, gamename_size, deh_sub,
+                       STRIFE_VERSION / 100, STRIFE_VERSION % 100);
 
             while (gamename[0] != '\0' && isspace(gamename[0]))
             {
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -985,8 +985,8 @@
             {
                 static char turbomessage[80];
                 extern char player_names[8][16];
-                snprintf(turbomessage, sizeof(turbomessage),
-                         "%s is turbo!", player_names[i]);
+                M_snprintf(turbomessage, sizeof(turbomessage),
+                           "%s is turbo!", player_names[i]);
                 players[consoleplayer].message = turbomessage;
                 turbodetected[i] = false;
             }
@@ -1290,7 +1290,7 @@
     char mapbuf[33];
 
     memset(mapbuf, 0, sizeof(mapbuf));
-    snprintf(mapbuf, sizeof(mapbuf), "%d", map);
+    M_snprintf(mapbuf, sizeof(mapbuf), "%d", map);
 
     // haleyjd: free if already set, and use M_SafeFilePath
     if(loadpath)
@@ -1805,7 +1805,7 @@
     
     // [STRIFE] custom save file path logic
     memset(gamemapstr, 0, sizeof(gamemapstr));
-    snprintf(gamemapstr, sizeof(gamemapstr), "%d", gamemap);
+    M_snprintf(gamemapstr, sizeof(gamemapstr), "%d", gamemap);
     savegame_file = M_SafeFilePath(path, gamemapstr);
 
     // [STRIFE] write the "current" file, which tells which hub map
@@ -1870,7 +1870,7 @@
     // [STRIFE]: custom message logic
     if(!strcmp(path, savepath))
     {
-        snprintf(savename, sizeof(savename), "%s saved.", character_name);
+        M_snprintf(savename, sizeof(savename), "%s saved.", character_name);
         players[consoleplayer].message = savename;
     }
 
@@ -2195,7 +2195,7 @@
     usergame = false;
     demoname_size = strlen(name) + 5;
     demoname = Z_Malloc(demoname_size, PU_STATIC, NULL);
-    snprintf(demoname, demoname_size, "%s.lmp", name);
+    M_snprintf(demoname, demoname_size, "%s.lmp", name);
     maxsize = 0x20000;
 
     //!
@@ -2290,8 +2290,8 @@
     }
 
     // Unknown version. Who knows?
-    snprintf(resultbuf, sizeof(resultbuf),
-             "%i.%i (unknown)", version / 100, version % 100);
+    M_snprintf(resultbuf, sizeof(resultbuf),
+               "%i.%i (unknown)", version / 100, version % 100);
 
     return resultbuf;
 }
--- a/src/strife/m_saves.c
+++ b/src/strife/m_saves.c
@@ -222,7 +222,7 @@
     char tmpnum[33];
 
     // haleyjd: no itoa available...
-    snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap);
+    M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap);
 
     // haleyjd: use M_SafeFilePath, not sprintf
     mapsave  = M_SafeFilePath(savepath, tmpnum);
@@ -251,7 +251,7 @@
     char tmpnum[33];
 
     // haleyjd: no itoa available...
-    snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap);
+    M_snprintf(tmpnum, sizeof(tmpnum), "%d", gamemap);
 
     mapsave  = M_SafeFilePath(savepathtemp, tmpnum);
     heresave = M_SafeFilePath(savepathtemp, "here");
@@ -437,7 +437,7 @@
     // that either basepath or newcomponent includes a redundant slash at the
     // end or beginning respectively.
     newstrlen = M_StringAlloc(&newstr, 3, 1, basepath, "/", newcomponent);
-    snprintf(newstr, newstrlen, "%s/%s", basepath, newcomponent);
+    M_snprintf(newstr, newstrlen, "%s/%s", basepath, newcomponent);
     M_NormalizeSlashes(newstr);
 
     return newstr;
@@ -477,8 +477,8 @@
 {
     static char tmpbuffer[32];
 
-    snprintf(tmpbuffer, sizeof(tmpbuffer),
-             "strfsav%d.ssg%s", slotnum, extra);
+    M_snprintf(tmpbuffer, sizeof(tmpbuffer),
+               "strfsav%d.ssg%s", slotnum, extra);
 
     return tmpbuffer;
 }
--- a/src/strife/p_inter.c
+++ b/src/strife/p_inter.c
@@ -971,8 +971,8 @@
         EV_DoDoor(&junk, close);
         P_NoiseAlert(players[0].mo, players[0].mo);
 
-        snprintf(plrkilledmsg, sizeof(plrkilledmsg),
-                 "%s", DEH_String("You're dead!  You set off the alarm."));
+        M_snprintf(plrkilledmsg, sizeof(plrkilledmsg),
+                   "%s", DEH_String("You're dead!  You set off the alarm."));
         if(!deathmatch)
             players[consoleplayer].message = plrkilledmsg;
 
@@ -1011,8 +1011,8 @@
     case MT_TOKEN_ALARM:
         P_NoiseAlert(players[0].mo, players[0].mo);
 
-        snprintf(plrkilledmsg, sizeof(plrkilledmsg),
-                 "%s", DEH_String("You Fool!  You've set off the alarm"));
+        M_snprintf(plrkilledmsg, sizeof(plrkilledmsg),
+                   "%s", DEH_String("You Fool!  You've set off the alarm"));
         if(!deathmatch)
             players[consoleplayer].message = plrkilledmsg;
         return;
--- a/src/strife/p_saveg.c
+++ b/src/strife/p_saveg.c
@@ -32,6 +32,7 @@
 #include "deh_main.h"
 #include "i_system.h"
 #include "z_zone.h"
+#include "m_misc.h"
 #include "p_local.h"
 #include "p_saveg.h"
 
@@ -80,7 +81,7 @@
 
     DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
 
-    snprintf(filename, filename_size, "%s%s", savegamedir, basename);
+    M_snprintf(filename, filename_size, "%s%s", savegamedir, basename);
 
     return filename;
 }
@@ -1609,7 +1610,7 @@
     */
 
     memset (name,0,sizeof(name)); 
-    snprintf(name, sizeof(name), "ver %i", STRIFE_VERSION);
+    M_snprintf(name, sizeof(name), "ver %i", STRIFE_VERSION);
 
     for (i=0; i<VERSIONSIZE; ++i)
         saveg_write8(name[i]);
@@ -1649,7 +1650,7 @@
         read_vcheck[i] = saveg_read8();
 
     memset (vcheck,0,sizeof(vcheck));
-    snprintf(vcheck, sizeof(vcheck), "ver %i", STRIFE_VERSION);
+    M_snprintf(vcheck, sizeof(vcheck), "ver %i", STRIFE_VERSION);
     if (strcmp(read_vcheck, vcheck) != 0)
         return false;                       // bad version 
 
--- a/src/strife/p_user.c
+++ b/src/strife/p_user.c
@@ -39,6 +39,7 @@
 #include "z_zone.h"
 #include "w_wad.h"
 #include "p_pspr.h"
+#include "m_misc.h"
 #include "m_random.h"
 #include "s_sound.h"
 #include "p_inter.h"
@@ -861,8 +862,8 @@
         if(name == NULL)
             name = "Item";
 
-        snprintf(useinventorymsg, sizeof(useinventorymsg),
-                 "You used the %s.", name);
+        M_snprintf(useinventorymsg, sizeof(useinventorymsg),
+                   "You used the %s.", name);
         player->message = useinventorymsg;
 
         if(player == &players[consoleplayer])
--- a/src/strife/s_sound.c
+++ b/src/strife/s_sound.c
@@ -788,7 +788,7 @@
     // get lumpnum if neccessary
     if (!music->lumpnum)
     {
-        snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name));
+        M_snprintf(namebuf, sizeof(namebuf), "d_%s", DEH_String(music->name));
         music->lumpnum = W_GetNumForName(namebuf);
     }
 
--- a/src/strife/st_stuff.c
+++ b/src/strife/st_stuff.c
@@ -54,6 +54,7 @@
 #include "am_map.h"
 #include "m_cheat.h"
 #include "m_menu.h" // villsa [STRIFE]
+#include "m_misc.h"
 
 #include "s_sound.h"
 
@@ -663,11 +664,11 @@
     {
         // [STRIFE] 'GPS' for player position
         static char buf[ST_MSGWIDTH];
-        snprintf(buf, sizeof(buf),
-                "ang=0x%x;x,y=(0x%x,0x%x)",
-                players[consoleplayer].mo->angle,
-                players[consoleplayer].mo->x,
-                players[consoleplayer].mo->y);
+        M_snprintf(buf, sizeof(buf),
+                   "ang=0x%x;x,y=(0x%x,0x%x)",
+                   players[consoleplayer].mo->angle,
+                   players[consoleplayer].mo->x,
+                   players[consoleplayer].mo->y);
         plyr->message = buf;
     }
 
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -818,7 +818,7 @@
 
     for (i=0; i<=99; i++)
     {
-        snprintf(lbmname, sizeof(lbmname), format, i, ext);
+        M_snprintf(lbmname, sizeof(lbmname), format, i, ext);
 
         if (!M_FileExists(lbmname))
         {