Skip to content

Commit ec9adb8

Browse files
committed
Add error messages back to Q_strncpyz/Q_strcat
Add Q_strnlen Use hardened Q_atoi/Q_atof inspired by etlegacy&etjump since atoi/atof can crap out on invalid inputs Simplify source code filenames to only show relative paths in warning/error messages.
1 parent 65e5b4c commit ec9adb8

46 files changed

Lines changed: 421 additions & 360 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

code/api/et/q_shared.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ void Parse1DMatrix( const char **buf_p, int x, float *m ) {
450450

451451
for (i = 0 ; i < x; i++) {
452452
token = COM_Parse( buf_p );
453-
m[i] = atof( token );
453+
m[i] = Q_atof( token );
454454
}
455455

456456
COM_MatchToken( buf_p, ")" );

code/api/shared/q_string.c

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ If you have questions concerning this license or the applicable additional terms
4343
#include <math.h>
4444
#include <stddef.h>
4545
#include <stdio.h>
46+
#include <stdarg.h>
4647
#include <stdlib.h>
4748
#include <string.h>
4849

@@ -207,19 +208,51 @@ qboolean Q_isintegral( float f )
207208
return (qboolean)( (int)f == f );
208209
}
209210

211+
#ifdef _WIN32
212+
#define QDECL __cdecl
213+
#define NORETURN __declspec(noreturn)
214+
#define FORMAT_PRINTF(x, y) /* nothing */
215+
#elif defined(__GNUC__) || defined(__clang__)
216+
#define QDECL
217+
#define NORETURN __attribute__((noreturn))
218+
#define FORMAT_PRINTF(x, y) __attribute__((format (printf, x, y)))
219+
#else
220+
#define QDECL
221+
#define NORETURN /* nothing */
222+
#endif
223+
224+
void NORETURN trap_Error(const char *fmt);
225+
226+
static void FORMAT_PRINTF(1,2) NORETURN QDECL Lib_Error( const char *error, ... ) {
227+
va_list argptr;
228+
char text[8192];
229+
230+
va_start (argptr, error);
231+
Q_vsnprintf (text, sizeof(text), error, argptr);
232+
va_end (argptr);
233+
234+
trap_Error( text );
235+
}
236+
210237
/*
211238
=============
212239
Q_strncpyz
213240
214241
Safe strncpy that ensures a trailing zero
215242
=============
216243
*/
217-
void Q_strncpyz( char *dest, const char *src, int destsize ) {
218-
assert(src);
219-
assert(dest);
220-
assert(destsize);
244+
void Q_strncpyz_fn( char *dest, const char *src, const int destsize, const char *func, const char *file, const int line ) {
245+
if (!dest) {
246+
Lib_Error("Q_strncpyz: NULL dest (%s, %s:%i)", func, file, line);
247+
}
248+
if (!src) {
249+
Lib_Error("Q_strncpyz: NULL src (%s, %s:%i)", func, file, line);
250+
}
251+
if (destsize < 1) {
252+
Lib_Error("Q_strncpyz: destsize < 1 (%s, %s:%i)", func, file, line);
253+
}
221254

222-
strncpy( dest, src, destsize-1 );
255+
strncpy( dest, src, (size_t)destsize-1 );
223256
dest[destsize-1] = '\0';
224257
}
225258

@@ -386,20 +419,30 @@ char *Q_strupr( char *s1 ) {
386419
}
387420

388421
// never goes past bounds or leaves without a terminating 0
389-
void Q_strcat( char *dest, int size, const char *src ) {
390-
int l1;
422+
void Q_strcat_fn( char *dest, const int size, const char *src, const char *func, const char *file, const int line ) {
423+
const int l1 = (int)strlen( dest );
391424

392-
l1 = strlen( dest );
393425
if ( l1 >= size ) {
394-
//Com_Error( ERR_FATAL, "Q_strcat: already overflowed" );
395-
return;
426+
Lib_Error( "Q_strcat: already overflowed" );
427+
//return;
396428
}
397429
if ( strlen(src)+1 > (size_t)(size - l1))
398430
{ //do the error here instead of in Q_strncpyz to get a meaningful msg
399-
//Com_Error(ERR_FATAL,"Q_strcat: cannot append \"%s\" to \"%s\"", src, dest);
400-
return;
431+
Lib_Error("Q_strcat: cannot append \"%s\" to \"%s\"", src, dest);
432+
//return;
433+
}
434+
Q_strncpyz_fn( dest + l1, src, size - l1, func, file, line );
435+
}
436+
437+
size_t Q_strnlen_fn(const char *str, size_t strsz, const char *func, const char *file, const int line ) {
438+
const char *p;
439+
if (!str) {
440+
Lib_Error("Q_strnlen: NULL str (%s, %s:%i)", func, file, line);
441+
//return 0;
401442
}
402-
Q_strncpyz( dest + l1, src, size - l1 );
443+
444+
p = memchr(str, 0, strsz);
445+
return p ? p - str : strsz;
403446
}
404447

405448
char *Q_stradd( char *dst, const char *src )
@@ -687,3 +730,11 @@ int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
687730
}
688731
#endif
689732

733+
float Q_atof(const char *str) {
734+
const float f = strtof(str, NULL);
735+
return (isfinite(f) ? f : 0);
736+
}
737+
738+
int Q_atoi(const char *str) {
739+
return (int)strtol(str, NULL, 10);
740+
}

code/api/shared/q_string.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,16 @@ int Q_stricmpn(const char *s1, const char *s2, int n);
6565
char *Q_strlwr( char *s1 );
6666
char *Q_strupr( char *s1 );
6767

68+
// relative path to a source file (src/foo/bar.c)
69+
#define RELATIVE_FILENAME ((__FILE__) + (SOURCE_PATH_SIZE))
70+
6871
// buffer size safe library replacements
69-
void Q_strncpyz( char *dest, const char *src, int destsize );
70-
void Q_strcat( char *dest, int size, const char *src );
72+
#define Q_strncpyz(dest, src, destsize) Q_strncpyz_fn(dest, src, destsize, __func__, RELATIVE_FILENAME, __LINE__)
73+
#define Q_strcat(dest, size, src) Q_strcat_fn(dest, size, src, __func__, RELATIVE_FILENAME, __LINE__)
74+
#define Q_strnlen(str, strsz ) Q_strnlen_fn(str, strsz, __func__, RELATIVE_FILENAME, __LINE__)
75+
void Q_strncpyz_fn( char *dest, const char *src, const int destsize, const char *func, const char *file, int line );
76+
void Q_strcat_fn( char *dest, const int size, const char *src, const char *func, const char *file, int line );
77+
size_t Q_strnlen_fn(const char *str, size_t strsz, const char *func, const char *file, int line );
7178

7279
const char *Q_stristr( const char *s, const char *find);
7380

@@ -95,6 +102,9 @@ char *Q_CleanDirName( char *dirname );
95102
#define Q_vsnprintf vsnprintf
96103
#endif
97104

105+
float Q_atof(const char *str);
106+
int Q_atoi(const char *str);
107+
98108
#if defined(__cplusplus)
99109
} // extern "C"
100110
#endif

code/cgame/cg_atmospheric.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -730,11 +730,11 @@ static void CG_EP_ParseFloats( const char *floatstr, float *f1, float *f2 )
730730
if( *middleptr )
731731
{
732732
*middleptr++ = '\0';
733-
*f1 = atof( floatstr );
734-
*f2 = atof( middleptr );
733+
*f1 = Q_atof( floatstr );
734+
*f2 = Q_atof( middleptr );
735735
}
736736
else {
737-
*f1 = *f2 = atof( floatstr );
737+
*f1 = *f2 = Q_atof( floatstr );
738738
}
739739
}
740740

@@ -750,11 +750,11 @@ static void CG_EP_ParseInts( const char *intstr, int *i1, int *i2 )
750750
if( *middleptr )
751751
{
752752
*middleptr++ = '\0';
753-
*i1 = atof( intstr );
754-
*i2 = atof( middleptr );
753+
*i1 = Q_atof( intstr );
754+
*i2 = Q_atof( middleptr );
755755
}
756756
else {
757-
*i1 = *i2 = atof( intstr );
757+
*i1 = *i2 = Q_atof( intstr );
758758
}
759759
}
760760

code/cgame/cg_consolecmds.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,9 @@ static void CG_Q3F_DumpSpeaker( void )
466466
Q_strncpyz( buff, buff, buffptr - buff + 1 );
467467

468468
if( !Q_stricmp( buff, "wait" ) )
469-
wait = atoi( valueptr );
469+
wait = Q_atoi( valueptr );
470470
else if( !Q_stricmp( buff, "random" ) )
471-
random = atoi( valueptr );
471+
random = Q_atoi( valueptr );
472472
}
473473

474474
// Open locations file
@@ -1291,27 +1291,27 @@ static void CG_Q3F_Discard_f( void ) {
12911291
}
12921292

12931293
trap_Cvar_VariableStringBuffer(va("discard_%s_cells", cls->commandstring), buffer, 256);
1294-
cells = atoi(buffer);
1294+
cells = Q_atoi(buffer);
12951295

12961296
trap_Cvar_VariableStringBuffer(va("discard_%s_shells", cls->commandstring), buffer, 256);
1297-
shells = atoi(buffer);
1297+
shells = Q_atoi(buffer);
12981298

12991299
trap_Cvar_VariableStringBuffer(va("discard_%s_rockets", cls->commandstring), buffer, 256);
1300-
rockets = atoi(buffer);
1300+
rockets = Q_atoi(buffer);
13011301

13021302
if(cells == -1) {
13031303
trap_Cvar_VariableStringBuffer("discard_cells", buffer, 256);
1304-
cells = atoi(buffer);
1304+
cells = Q_atoi(buffer);
13051305
}
13061306

13071307
if(shells == -1) {
13081308
trap_Cvar_VariableStringBuffer("discard_shells", buffer, 256);
1309-
shells = atoi(buffer);
1309+
shells = Q_atoi(buffer);
13101310
}
13111311

13121312
if(rockets == -1) {
13131313
trap_Cvar_VariableStringBuffer("discard_rockets", buffer, 256);
1314-
rockets = atoi(buffer);
1314+
rockets = Q_atoi(buffer);
13151315
}
13161316

13171317
trap_SendConsoleCommand(va("discard_etf %d %d %d\n", cells, shells, rockets));

code/cgame/cg_local.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,7 +2185,7 @@ void trap_R_ClearDecals( void );
21852185

21862186
// normal sounds will have their volume dynamically changed as their entity
21872187
// moves and the listener moves
2188-
#define trap_S_StartSound( origin, entityNum, entchannel, sfx ) trap_S_RealStartSound( origin, entityNum, entchannel, sfx, __FILE__, __LINE__ )
2188+
#define trap_S_StartSound( origin, entityNum, entchannel, sfx ) trap_S_RealStartSound( origin, entityNum, entchannel, sfx, RELATIVE_FILENAME, __LINE__ )
21892189
void trap_S_RealStartSound( const vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx, const char* file, int line );
21902190
void trap_S_StartSoundVControl( const vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx, int volume );
21912191
void trap_S_StartSoundEx( const vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx, int flags );
@@ -2195,7 +2195,7 @@ int trap_S_GetSoundLength(sfxHandle_t sfx);
21952195
int trap_S_GetCurrentSoundTime( void ); // ydnar
21962196

21972197
// a local sound is always played full volume
2198-
#define trap_S_StartLocalSound( sfx, channelNum ) trap_S_RealStartLocalSound( sfx, channelNum, __FILE__, __LINE__ )
2198+
#define trap_S_StartLocalSound( sfx, channelNum ) trap_S_RealStartLocalSound( sfx, channelNum, RELATIVE_FILENAME, __LINE__ )
21992199
void trap_S_RealStartLocalSound( sfxHandle_t sfx, int channelNum, const char* file, int line );
22002200
//void trap_S_ClearLoopingSounds( void );
22012201
void trap_S_ClearSounds( qboolean killmusic );

code/cgame/cg_main.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ static const int cvarLimitTableSize = (int)ARRAY_LEN( cvarLimitTable );
218218
CG_LimitCvars
219219
=================
220220
*/
221-
void CG_LimitCvars( void ) {
221+
static void CG_LimitCvars( void ) {
222222
int i;
223223
cvarLimitTable_t *cvl;
224224

@@ -272,23 +272,23 @@ void CG_LimitCvars( void ) {
272272
CG_Q3F_UpdateCvarLimits
273273
=================
274274
*/
275-
void CG_Q3F_UpdateCvarLimit( const char *cvarname, int *min, int *max ) {
275+
static void CG_Q3F_UpdateCvarLimit( const char *cvarname, int *cvmin, int *cvmax ) {
276276
int i;
277277
cvarLimitTable_t *cvl;
278278

279279
for ( i = 0, cvl = cvarLimitTable; i < cvarLimitTableSize ; i++, cvl++ ) {
280280
if( !Q_stricmp( cvarname, cvl->cvarName ) ) {
281-
cvl->min = *min;
282-
cvl->max = *max;
281+
cvl->min = *cvmin;
282+
cvl->max = *cvmax;
283283
break;
284284
}
285285
}
286286
}
287287

288288
void CG_Q3F_UpdateCvarLimits(void) {
289289
const char *ptr;
290-
char cvarname[64], buff[16];
291-
int min, max;
290+
char cvarname[64] = { 0 }, buff[16] = { 0 };
291+
int cvmin, cvmax;
292292
size_t len;
293293

294294
ptr = CG_ConfigString( CS_Q3F_CVARLIMITS );
@@ -299,25 +299,25 @@ void CG_Q3F_UpdateCvarLimits(void) {
299299
}
300300
while( *ptr && *ptr == ' ' )
301301
ptr++;
302-
cvarname[len] = 0;
302+
cvarname[len] = '\0';
303303

304304
for( len = 0; *ptr && *ptr != ' ' && len < (sizeof(buff) - 1); len++ ) {
305305
buff[len] = *ptr++;
306306
}
307307
while( *ptr && *ptr == ' ' )
308308
ptr++;
309-
buff[len] = 0;
310-
min = atoi(buff);
309+
buff[len] = '\0';
310+
cvmin = Q_atoi(buff);
311311

312312
for( len = 0; *ptr && *ptr != ' ' && len < (sizeof(buff) - 1); len++ ) {
313313
buff[len] = *ptr++;
314314
}
315315
while( *ptr && *ptr == ' ' )
316316
ptr++;
317-
buff[len] = 0;
318-
max = atoi(buff);
317+
buff[len] = '\0';
318+
cvmax = Q_atoi(buff);
319319

320-
CG_Q3F_UpdateCvarLimit( cvarname, &min, &max );
320+
CG_Q3F_UpdateCvarLimit( cvarname, &cvmin, &cvmax );
321321
}
322322
}
323323

@@ -418,7 +418,7 @@ void CG_RegisterCvars( void ) {
418418

419419
// see if we are also running the server on this machine
420420
trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) );
421-
cgs.localServer = atoi( var );
421+
cgs.localServer = Q_atoi( var );
422422

423423
cgs.grenadePrimeSoundModificationCount = cg_grenadePrimeSound.modificationCount;
424424
cgs.drawSkyPortalModificationCount = cg_drawSkyPortal.modificationCount;
@@ -614,7 +614,7 @@ void CG_Q3F_PlayLocalSound( const char *sound )
614614
soundid = -1;
615615

616616
if( soundid == -2 )
617-
soundid = (sfxHandle_t)atoi( sound );
617+
soundid = (sfxHandle_t)Q_atoi( sound );
618618

619619
if ( soundid >= 0 && soundid < MAX_SOUNDS )
620620
{
@@ -1296,7 +1296,7 @@ void CG_LoadMenus(const char *menuFile, qboolean resetHud) {
12961296
}
12971297

12981298
trap_FS_Read( buf, len, f );
1299-
buf[len] = 0;
1299+
buf[len] = '\0';
13001300
trap_FS_FCloseFile( f );
13011301

13021302
COM_Compress(buf);
@@ -1372,8 +1372,8 @@ void CG_LoadMenus(const char *menuFile, qboolean resetHud) {
13721372
}
13731373
}
13741374

1375-
x = atof(_p);
1376-
y = atof(p2);
1375+
x = Q_atof(_p);
1376+
y = Q_atof(p2);
13771377

13781378
menu = Menus_FindByName( linebuff );
13791379

@@ -1978,7 +1978,7 @@ static float CG_Cvar_Get(const char *cvar) {
19781978
char buff[128];
19791979
memset(buff, 0, sizeof(buff));
19801980
trap_Cvar_VariableStringBuffer(cvar, buff, sizeof(buff));
1981-
return atof(buff);
1981+
return Q_atof(buff);
19821982
}
19831983

19841984
void CG_Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style, fontStruct_t *parentfont, int textalignment) {
@@ -2062,7 +2062,7 @@ static void CG_RunCinematicFrame(int handle) {
20622062
}
20632063

20642064
static void CG_S_StartLocalSound( sfxHandle_t sfx, int channelNum ) {
2065-
trap_S_RealStartLocalSound(sfx, channelNum, __FILE__, __LINE__ );
2065+
trap_S_RealStartLocalSound(sfx, channelNum, RELATIVE_FILENAME, __LINE__ );
20662066
}
20672067

20682068
qboolean CG_FileExists( const char *filename ) {

0 commit comments

Comments
 (0)