From 276a31ba5173770b72faa6abb3778aee1d71150d Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Tue, 30 Jan 2024 21:38:52 +1000 Subject: [PATCH] Work around Microsoft's broken vsnprintf implementation Microsoft's documentation says it has supported %zu (C99 standard format for size_t) for some years but trying to use it causes crashes at least on older versions of Windows. Makes dpsnprintf and dpvsnprintf documentation more accessible (these funcs have different return behaviour than the C standard ones). Signed-off-by: bones_was_here --- cmd.c | 4 ++-- common.c | 10 +++++----- common.h | 11 +++++++---- prvm_cmds.c | 2 +- prvm_edict.c | 4 ++-- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/cmd.c b/cmd.c index 0dfc093d..bf4cc014 100644 --- a/cmd.c +++ b/cmd.c @@ -269,7 +269,7 @@ void Cbuf_AddText (cmd_state_t *cmd, const char *text) if (cbuf->size + l > cbuf->maxsize) { - Con_Printf(CON_WARN "Cbuf_AddText: input too large, %zuKB ought to be enough for anybody.\n", cbuf->maxsize / 1024); + Con_Printf(CON_WARN "Cbuf_AddText: input too large, %luKB ought to be enough for anybody.\n", (unsigned long)(cbuf->maxsize / 1024)); return; } @@ -297,7 +297,7 @@ void Cbuf_InsertText (cmd_state_t *cmd, const char *text) if (cbuf->size + l > cbuf->maxsize) { - Con_Printf(CON_WARN "Cbuf_InsertText: input too large, %zuKB ought to be enough for anybody.\n", cbuf->maxsize / 1024); + Con_Printf(CON_WARN "Cbuf_InsertText: input too large, %luKB ought to be enough for anybody.\n", (unsigned long)(cbuf->maxsize / 1024)); return; } diff --git a/common.c b/common.c index 06afb60f..cf2fb248 100644 --- a/common.c +++ b/common.c @@ -1021,9 +1021,9 @@ int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list ar buffer[buffersize - 1] = '\0'; // we could be inside Con_Printf if (result < 0) - Sys_Printf("dpvsnprintf: output error, buffer size %zu\n", buffersize); + Sys_Printf("dpvsnprintf: output error, buffer size %lu\n", (unsigned long)buffersize); else - Sys_Printf("dpvsnprintf: truncated to %zu bytes: \"%s\"\n", buffersize - 1, buffer); + Sys_Printf("dpvsnprintf: truncated to %lu bytes: \"%s\"\n", (unsigned long)buffersize - 1, buffer); return -1; } @@ -1361,7 +1361,7 @@ char *dp_stpecpy(char *dst, char *end, const char *src) if (p) return p - 1; end[-1] = '\0'; - Con_Printf(CON_WARN "%s: src string unterminated or truncated to %zu bytes: \"%s\"\n", __func__, dst == end ? 0 : (end - dst) - 1, dst); + Con_Printf(CON_WARN "%s: src string unterminated or truncated to %lu bytes: \"%s\"\n", __func__, (unsigned long)(dst == end ? 0 : (end - dst) - 1), dst); return end; } @@ -1374,7 +1374,7 @@ char *dp_ustr2stp(char *dst, size_t dsize, const char *src, size_t slen) if (slen >= dsize) { slen = dsize - 1; - Con_Printf(CON_WARN "%s: src string truncated to %zu bytes: \"%.*s\"\n", __func__, slen, (int)slen, src); + Con_Printf(CON_WARN "%s: src string truncated to %lu bytes: \"%.*s\"\n", __func__, (unsigned long)slen, (int)slen, src); } memcpy(dst, src, slen); dst[slen] = '\0'; @@ -1394,7 +1394,7 @@ size_t dp__strlcpy(char *dst, const char *src, size_t dsize, const char *func, u if (p) return (p - 1) - dst; dst[dsize - 1] = '\0'; - Con_Printf(CON_WARN "%s:%u: src string unterminated or truncated to %zu bytes: \"%s\"\n", func, line, dsize - 1, dst); + Con_Printf(CON_WARN "%s:%u: src string unterminated or truncated to %lu bytes: \"%s\"\n", func, line, (unsigned long)dsize - 1, dst); return dsize - 1; } diff --git a/common.h b/common.h index 1414e633..fe7b332f 100644 --- a/common.h +++ b/common.h @@ -234,11 +234,14 @@ char *va(char *buf, size_t buflen, const char *format, ...) DP_FUNC_PRINTF(3); #undef vsnprintf #define vsnprintf DP_STATIC_ASSERT(0, "vsnprintf is forbidden for portability reasons. Use dpvsnprintf instead.") -// dpsnprintf and dpvsnprintf -// return the number of printed characters, excluding the final '\0' -// or return -1 if the buffer isn't big enough to contain the entire string. -// buffer is ALWAYS null-terminated +// documentation duplicated deliberately for the benefit of IDEs that support https://www.doxygen.nl/manual/docblocks.html +/// Returns the number of printed characters, excluding the final '\0' +/// or returns -1 if the buffer isn't big enough to contain the entire string. +/// Buffer is ALWAYS null-terminated. extern int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...) DP_FUNC_PRINTF(3); +/// Returns the number of printed characters, excluding the final '\0' +/// or returns -1 if the buffer isn't big enough to contain the entire string. +/// Buffer is ALWAYS null-terminated. extern int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args); // A bunch of functions are forbidden for security reasons (and also to please MSVS 2005, for some of them) diff --git a/prvm_cmds.c b/prvm_cmds.c index 9a4e6921..bfe40a3b 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -296,7 +296,7 @@ size_t VM_VarString(prvm_prog_t *prog, int first, char *out, size_t outsize) out = p - 1; else { - VM_Warning(prog, "%zu of %zu bytes available, will truncate %zu byte string \"%s\"\n", outend - out, outsize - 1, strlen(s), s); + VM_Warning(prog, "%lu of %lu bytes available, will truncate %lu byte string \"%s\"\n", (unsigned long)(outend - out), (unsigned long)outsize - 1, (unsigned long)strlen(s), s); out = outend; *out = '\0'; } diff --git a/prvm_edict.c b/prvm_edict.c index 323f40a2..c0b6865e 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -3377,12 +3377,12 @@ int PRVM_SetTempString(prvm_prog_t *prog, const char *s, size_t slen) return 0; size = slen + 1; if (developer_insane.integer) - Con_DPrintf("PRVM_SetTempString %s: cursize %i, size %zu\n", prog->name, prog->tempstringsbuf.cursize, size); + Con_DPrintf("PRVM_SetTempString %s: cursize %i, size %lu\n", prog->name, prog->tempstringsbuf.cursize, (unsigned long)size); if ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size) { sizebuf_t old = prog->tempstringsbuf; if (prog->tempstringsbuf.cursize + size >= 1<<28) - prog->error_cmd("PRVM_SetTempString %s: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, size %zu)\n", prog->name, prog->tempstringsbuf.cursize, size); + prog->error_cmd("PRVM_SetTempString %s: ran out of tempstring memory! (refusing to grow tempstring buffer over 256MB, cursize %i, size %lu)\n", prog->name, prog->tempstringsbuf.cursize, (unsigned long)size); prog->tempstringsbuf.maxsize = max(prog->tempstringsbuf.maxsize, 65536); while ((size_t)prog->tempstringsbuf.maxsize < prog->tempstringsbuf.cursize + size) prog->tempstringsbuf.maxsize *= 2; -- 2.39.2