diff --git a/engine/common/common.c b/engine/common/common.c index e236ecd3f..e44281fba 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -206,6 +206,7 @@ qboolean VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list a //windows/linux have inconsistant snprintf //this is an attempt to get them consistant and safe //size is the total size of the buffer +//returns true on overflow (will be truncated). qboolean VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...) { va_list argptr; diff --git a/engine/common/common.h b/engine/common/common.h index 918618039..c294898c3 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #endif - +#define VK_NO_STDINT_H //we're handling this. please don't cause conflicts. grr. #if __STDC_VERSION__ >= 199901L || defined(__GNUC__) //C99 has a stdint header which hopefully contains an intptr_t //its optional... but if its not in there then its unlikely you'll actually be able to get the engine to a stage where it *can* load anything @@ -44,6 +44,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define qint64_t int64_t #define quint64_t uint64_t #else + #define qint8_t signed char //be explicit with this one. + #define quint8_t unsigned char #define qint16_t short #define quint16_t unsigned short #define qint32_t int @@ -84,6 +86,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #ifndef uint32_t + #define int8_t qint8_t + #define uint8_t quint8_t #define int16_t qint16_t #define uint16_t quint16_t #define int32_t qint32_t diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index d21f9cc01..635b16a91 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -300,7 +300,7 @@ static unsigned int QDECL FSSTDIO_CreateLoc(searchpathfuncs_t *handle, flocation loc->len = 0; loc->offset = 0; loc->fhandle = handle; - if ((unsigned int)snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", sp->rootpath, filename) > sizeof(loc->rawname)-1) + if (Q_snprintfz(loc->rawname, sizeof(loc->rawname), "%s/%s", sp->rootpath, filename)) return FF_NOTFOUND; //too long... for (ofs = loc->rawname+1 ; *ofs ; ofs++) @@ -333,7 +333,7 @@ static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t */ // check a file in the directory tree - if ((unsigned int)snprintf (netpath, sizeof(netpath), "%s/%s", sp->rootpath, filename) > sizeof(netpath)-1) + if (Q_snprintfz (netpath, sizeof(netpath), "%s/%s", sp->rootpath, filename)) return FF_NOTFOUND; #if 0//def ANDROID diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index ef736cf80..4eacc556c 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -3449,6 +3449,7 @@ static void Mod_LoadMiptex(model_t *loadmodel, texture_t *tx, miptex_t *mt, size else if (extsize <= 16) continue; //too small for an altformat lump else if (newdata != PTI_INVALID) continue; //only accept the first accepted format (allowing for eg astc+bc1 fallbacks) else if (!strncmp(extfmt, "RGBA", 4)) newfmt = PTI_RGBA8; //32bpp, we don't normally need this alpha precision (padding can be handy though, for the lazy). + else if (!strncmp(extfmt, "RGBX", 4)) newfmt = PTI_RGBX8; //32bpp, we don't normally need this alpha precision (padding can be handy though, for the lazy). else if (!strncmp(extfmt, "RGB", 4)) newfmt = PTI_RGB8; //24bpp else if (!strncmp(extfmt, "565", 4)) newfmt = PTI_RGB565; //16bpp else if (!strncmp(extfmt, "4444", 4)) newfmt = PTI_RGBA4444; //16bpp diff --git a/plugins/irc/ircclient.c b/plugins/irc/ircclient.c index 1032696bc..7aa769892 100644 --- a/plugins/irc/ircclient.c +++ b/plugins/irc/ircclient.c @@ -2119,7 +2119,7 @@ static int IRC_ClientFrame(ircclient_t *irc) *exc = '\0'; //a link to interact with the sender - if (Q_snprintf(link, sizeof(link), "^["COLOURGREEN"%s\\act\\user\\who\\%s^]", prefix, prefix) >= sizeof(link)) + if (Q_snprintfz(link, sizeof(link), "^["COLOURGREEN"%s\\act\\user\\who\\%s^]", prefix, prefix)) Q_snprintf(link, sizeof(link), "%s", prefix); if (!strncmp(col, "\001", 1)) diff --git a/plugins/jabber/jabberclient.c b/plugins/jabber/jabberclient.c index 6c9531609..58c959fa8 100644 --- a/plugins/jabber/jabberclient.c +++ b/plugins/jabber/jabberclient.c @@ -1118,11 +1118,11 @@ static int sasl_digestmd5_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, if (!*realm) Q_strlcpy(realm, ctx->domain, sizeof(realm)); - if (Q_snprintf(digesturi, sizeof(digesturi), "xmpp/%s", realm) >= sizeof(digesturi)) + if (Q_snprintfz(digesturi, sizeof(digesturi), "xmpp/%s", realm)) return -1; - if (Q_snprintf(X, sizeof(X), "%s:%s:", username, realm) >= sizeof(X)) + if (Q_snprintfz(X, sizeof(X), "%s:%s:", username, realm)) return -1; if (ctx->password_hash_size == 16 && !strcmp(X, ctx->password_validity)) memcpy(Y, ctx->password_hash, 16); //use the hashed password, instead of the (missing) plain one @@ -1130,7 +1130,7 @@ static int sasl_digestmd5_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, { Q_strlcpy(ctx->password_validity, X, sizeof(ctx->password_validity)); - if (Q_snprintf(X, sizeof(X), "%s:%s:%s", username, realm, ctx->password_plain) < sizeof(X)) + if (Q_snprintfz(X, sizeof(X), "%s:%s:%s", username, realm, ctx->password_plain)) return -1; MD5_ToBinary(X, strlen(X), Y, sizeof(Y)); @@ -1143,19 +1143,19 @@ static int sasl_digestmd5_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, memcpy(A1, Y, 16); if (*authzid) { - if (Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s:%s", nonce, cnonce, authzid) >= sizeof(A1)-16) + if (Q_snprintfz(A1+16, sizeof(A1)-16, ":%s:%s:%s", nonce, cnonce, authzid)) return -1; } else { - if (Q_snprintf(A1+16, sizeof(A1)-16, ":%s:%s", nonce, cnonce) >= sizeof(A1)-16) + if (Q_snprintfz(A1+16, sizeof(A1)-16, ":%s:%s", nonce, cnonce)) return -1; } - if (Q_snprintf(A2, sizeof(A2), "%s:%s", "AUTHENTICATE", digesturi) >= sizeof(A2)) + if (Q_snprintfz(A2, sizeof(A2), "%s:%s", "AUTHENTICATE", digesturi)) return -1; MD5_ToHex(A1, strlen(A1+16)+16, HA1, sizeof(HA1)); MD5_ToHex(A2, strlen(A2), HA2, sizeof(HA2)); - if (Q_snprintf(KD, sizeof(KD), "%s:%s:%s:%s:%s:%s", HA1, nonce, nc, cnonce, qop, HA2) >= sizeof(KD)) + if (Q_snprintfz(KD, sizeof(KD), "%s:%s:%s:%s:%s:%s", HA1, nonce, nc, cnonce, qop, HA2)) return -1; MD5_ToHex(KD, strlen(KD), Z, sizeof(Z)); @@ -2625,7 +2625,7 @@ qboolean JCL_Reconnect(jclient_t *jcl) //jcl->tlsconnect requires an explicit hostname, so should not be able to take this path. char srv[256]; char srvserver[256]; - if (Q_snprintf(srv, sizeof(srv), "_xmpp-client._tcp.%s", jcl->domain) < sizeof(srv) && NET_DNSLookup_SRV(srv, srvserver, sizeof(srvserver))) + if (!Q_snprintfz(srv, sizeof(srv), "_xmpp-client._tcp.%s", jcl->domain) && NET_DNSLookup_SRV(srv, srvserver, sizeof(srvserver))) { Con_DPrintf("XMPP: Trying to connect to %s (%s)\n", jcl->domain, srvserver); jcl->socket = netfuncs->TCPConnect(srvserver, jcl->serverport); //port is should already be part of the srvserver name @@ -5494,8 +5494,8 @@ int JCL_ClientFrame(jclient_t *jcl, char **error) unparsable = true; if (!strcmp(tree->name, "features")) { - if (Q_snprintf(jcl->barejid, sizeof(jcl->barejid), "%s@%s", jcl->username, jcl->domain) >= sizeof(jcl->barejid) || - Q_snprintf(jcl->fulljid, sizeof(jcl->fulljid), "%s@%s/%s", jcl->username, jcl->domain, jcl->resource) >= sizeof(jcl->fulljid)) + if (Q_snprintfz(jcl->barejid, sizeof(jcl->barejid), "%s@%s", jcl->username, jcl->domain) || + Q_snprintfz(jcl->fulljid, sizeof(jcl->fulljid), "%s@%s/%s", jcl->username, jcl->domain, jcl->resource)) { XML_Destroy(tree); return JCL_KILL; @@ -7204,7 +7204,7 @@ void JCL_Command(int accid, char *console) char roomserverhandle[512]; buddy_t *b; bresource_t *r; - if (Q_snprintf(roomserverhandle, sizeof(roomserverhandle), "%s@%s/%s", arg[1], arg[2], arg[3]) < sizeof(roomserverhandle) && JCL_FindBuddy(jcl, roomserverhandle, &b, &r, false)) + if (!Q_snprintfz(roomserverhandle, sizeof(roomserverhandle), "%s@%s/%s", arg[1], arg[2], arg[3]) && JCL_FindBuddy(jcl, roomserverhandle, &b, &r, false)) { JCL_AddClientMessagef(jcl, "", roomserverhandle); JCL_ForgetBuddy(jcl, b, NULL); diff --git a/plugins/jabber/jingle.c b/plugins/jabber/jingle.c index 10b97e821..bf1158be6 100644 --- a/plugins/jabber/jingle.c +++ b/plugins/jabber/jingle.c @@ -72,7 +72,7 @@ static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s //for msn, live.com has one, messanger.live.com has one, but messenger.live.com does NOT. seriously, the typo has more services. wtf microsoft? //google doesn't provide a stun srv entry //facebook doesn't provide a stun srv entry - if (Q_snprintf(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain) < sizeof(stunhost) && NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost))) + if (!Q_snprintfz(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain) && NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost))) piceapi->ICE_Set(ice, "stunip", stunhost); else { diff --git a/plugins/jabber/sift.c b/plugins/jabber/sift.c index df1e89049..e2736f764 100644 --- a/plugins/jabber/sift.c +++ b/plugins/jabber/sift.c @@ -342,7 +342,7 @@ void XMPP_FT_SendFile(jclient_t *jcl, const char *console, const char *to, const ft->transmitting = true; ft->blocksize = 4096; Q_strlcpy(ft->fname, fname, sizeof(ft->fname)); - if (Q_snprintf(ft->sid, sizeof(ft->sid), "%x%s", rand(), ft->fname) >= sizeof(ft->sid)) + if (Q_snprintfz(ft->sid, sizeof(ft->sid), "%x%s", rand(), ft->fname)) /*doesn't matter so long as its unique*/; Q_strlcpy(ft->md5hash, "", sizeof(ft->md5hash)); ft->size = filefuncs->Open(ft->fname, &ft->file, 1); diff --git a/plugins/plugin.c b/plugins/plugin.c index 44d6ba57f..1f52fd62e 100644 --- a/plugins/plugin.c +++ b/plugins/plugin.c @@ -104,27 +104,56 @@ char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t o return oout; } -#if defined(_MSC_VER) && _MSC_VER < 1900 -int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list argptr) -{ - int r = _vsnprintf (buffer, maxlen-1, format, argptr); - buffer[maxlen-1] = 0; //make sure its null terminated - if (r < 0) //work around dodgy return value. we can't use this to check required length but can check for truncation - r = maxlen; - return r; -} -int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) -{ - int p; - va_list argptr; - va_start (argptr, format); - p = Q_vsnprintf (buffer, maxlen, format,argptr); - va_end (argptr); - - return p; -} +//returns true on truncation +qboolean VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr) +{ + size_t ret; +#ifdef _WIN32 + //doesn't null terminate. + //returns -1 on truncation + ret = _vsnprintf (dest, size, fmt, argptr); + dest[size-1] = 0; //shitty paranoia +#else + //always null terminates. + //returns length regardless of truncation. + ret = vsnprintf (dest, size, fmt, argptr); #endif +#ifdef _DEBUG + if (ret>=size) + plugfuncs->Error("Q_vsnprintfz: Truncation\n"); +#endif + //if ret is -1 (windows oversize, or general error) then it'll be treated as unsigned so really long. this makes the following check quite simple. + return ret>=size; +} +//windows/linux have inconsistant snprintf +//this is an attempt to get them consistant and safe +//size is the total size of the buffer +//returns true on overflow (will be truncated). +qboolean VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...) +{ + va_list argptr; + size_t ret; + + va_start (argptr, fmt); +#ifdef _WIN32 + //doesn't null terminate. + //returns -1 on truncation + ret = _vsnprintf (dest, size, fmt, argptr); + dest[size-1] = 0; //shitty paranoia +#else + //always null terminates. + //returns length regardless of truncation. + ret = vsnprintf (dest, size, fmt, argptr); +#endif + va_end (argptr); +#ifdef _DEBUG + if (ret>=size) + plugfuncs->Error("Q_vsnprintfz: Truncation\n"); +#endif + //if ret is -1 (windows oversize, or general error) then it'll be treated as unsigned so really long. this makes the following check quite simple. + return ret>=size; +} char *va(const char *format, ...) //Identical in function to the one in Quake, though I can assure you that I wrote it... { //It's not exactly hard, just easy to use, so gets duplicated lots. @@ -132,7 +161,7 @@ char *va(const char *format, ...) //Identical in function to the one in Quake, t static char string[1024]; va_start (argptr, format); - Q_vsnprintf (string, sizeof(string), format,argptr); + Q_vsnprintfz (string, sizeof(string), format,argptr); va_end (argptr); return string; @@ -195,7 +224,7 @@ void Con_Printf(const char *format, ...) static char string[1024]; va_start (argptr, format); - Q_vsnprintf (string, sizeof(string), format,argptr); + Q_vsnprintfz (string, sizeof(string), format,argptr); va_end (argptr); plugfuncs->Print(string); @@ -209,7 +238,7 @@ void Con_DPrintf(const char *format, ...) return; va_start (argptr, format); - Q_vsnprintf (string, sizeof(string), format,argptr); + Q_vsnprintfz (string, sizeof(string), format,argptr); va_end (argptr); plugfuncs->Print(string); @@ -220,7 +249,7 @@ void Sys_Errorf(const char *format, ...) static char string[1024]; va_start (argptr, format); - Q_vsnprintf (string, sizeof(string), format,argptr); + Q_vsnprintfz (string, sizeof(string), format,argptr); va_end (argptr); plugfuncs->Error(string); diff --git a/plugins/plugin.h b/plugins/plugin.h index 462751310..00d7fd406 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -361,13 +361,11 @@ extern plugcvarfuncs_t *cvarfuncs; void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs); void Q_strlcpy(char *d, const char *s, int n); void Q_strlcat(char *d, const char *s, int n); -#if defined(_MSC_VER) && _MSC_VER < 2015 - int Q_snprintf(char *buffer, size_t maxlen, const char *format, ...) LIKEPRINTF(3); - int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs); -#else - #define Q_snprintf snprintf - #define Q_vsnprintf vsnprintf -#endif + +qboolean VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr); +qboolean VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...) LIKEPRINTF(3); +#define Q_snprintf (void)Q_snprintfz +#define Q_vsnprintf (void)Q_vsnprintfz char *va(const char *format, ...); qboolean Plug_Init(void);