]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
com: fix loop/crash in dpvsnprintf() error handling
authorbones_was_here <bones_was_here@xonotic.au>
Tue, 23 Jul 2024 21:32:50 +0000 (07:32 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Tue, 23 Jul 2024 21:32:50 +0000 (07:32 +1000)
Somehow I didn't notice Sys_Printf() calls dpvsnprintf(), see
21fa9010ae6de8792f36cca08cb77aaa95d4b928.

Also fixes a minor bug where Sys_Print() could output more bytes than it
should, introduced in 01642af37128bffc1accbf2e92cb2428ea570720.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
common.c
sys_shared.c

index f0f2fcce3842875b769c20b0f80e89e4f53439ac..0d701bca99864ea785ccdd3cf0762fb252f1b5ec 100644 (file)
--- a/common.c
+++ b/common.c
@@ -1018,12 +1018,27 @@ int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list ar
 #endif
        if (result < 0 || (size_t)result >= buffersize)
        {
-               buffer[buffersize - 1] = '\0';
-               // we could be inside Con_Printf
+               // _vsnprintf_s returns -1 on error and on truncation (indistinguishable),
+               // vsnprintf returns negative on error and the desired strlen on truncation.
+               buffer[buffersize - 1] = '\0'; // should be unnecessary, but just in case
+               // Basic stdout only: we could be inside Con_Printf, Sys_Printf calls dpvsnprintf,
+               // Windows console doesn't support colours.
                if (result < 0)
-                       Sys_Printf("dpvsnprintf: output error, buffer size %lu\n", (unsigned long)buffersize);
+                       Sys_Print("dpvsnprintf: output error!\n", 27);
                else
-                       Sys_Printf("dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer);
+               {
+                       char msg[MAX_INPUTLINE];
+#if _MSC_VER >= 1400
+                       result = _snprintf_s(msg, sizeof(msg), _TRUNCATE, "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer);
+#else
+                       result = snprintf(msg, sizeof(msg), "dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer);
+#endif
+                       if (result > 0)
+                       {
+                               msg[sizeof(msg) - 1] = '\n'; // may have been lost in truncation
+                               Sys_Print(msg, min((size_t)result, sizeof(msg)));
+                       }
+               }
                return -1;
        }
 
index 46cec64247666a080dd3ea44f17c09ea6acd5e23..b955e8278aedfd5b2ef42c3c3da05be618d28099 100644 (file)
@@ -629,12 +629,13 @@ void Sys_Print(const char *text, size_t textlen)
   #else
     #define write _write
   #endif
-               while(*text)
+               while(*text && textlen)
                {
                        fs_offset_t written = (fs_offset_t)write(sys.outfd, text, textlen);
                        if(written <= 0)
                                break; // sorry, I cannot do anything about this error - without an output
                        text += written;
+                       textlen -= written;
                }
   #ifndef WIN32
                if (sys_stdout_blocks.integer)