public: moved COM_ParseFileSafe to libpublic, added optional argument for length and overflow checking
This commit is contained in:
parent
a235bec5f1
commit
9e5d5e0ea3
|
@ -3078,9 +3078,7 @@ char *pfnParseFile( char *data, char *token )
|
|||
{
|
||||
char *out;
|
||||
|
||||
host.com_handlecolon = true;
|
||||
out = COM_ParseFile( data, token );
|
||||
host.com_handlecolon = false;
|
||||
out = _COM_ParseFileSafe( data, token, -1, PFILE_HANDLECOLON, NULL );
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -1106,6 +1106,17 @@ static void GAME_EXPORT UI_ShellExecute( const char *path, const char *parms, in
|
|||
Sys_Quit();
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
pfnParseFile
|
||||
|
||||
legacy wrapper
|
||||
==============
|
||||
*/
|
||||
static char *pfnParseFile( char *buf, char *token )
|
||||
{
|
||||
return COM_ParseFile( buf, token );
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
static ui_enginefuncs_t gEngfuncs =
|
||||
|
@ -1159,7 +1170,7 @@ static ui_enginefuncs_t gEngfuncs =
|
|||
CL_Active,
|
||||
pfnClientJoin,
|
||||
COM_LoadFileForMe,
|
||||
COM_ParseFile,
|
||||
pfnParseFile,
|
||||
COM_FreeFile,
|
||||
Key_ClearStates,
|
||||
Key_SetKeyDest,
|
||||
|
|
|
@ -861,9 +861,7 @@ void CL_QuakeExecStuff( void )
|
|||
|
||||
if( !*text ) break;
|
||||
|
||||
host.com_ignorebracket = true;
|
||||
text = COM_ParseFile( text, token );
|
||||
host.com_ignorebracket = false;
|
||||
text = _COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL );
|
||||
|
||||
if( !text ) break;
|
||||
|
||||
|
|
|
@ -335,7 +335,6 @@ static ref_api_t gEngfuncs =
|
|||
COM_GetProcAddress,
|
||||
|
||||
FS_LoadFile,
|
||||
COM_ParseFile,
|
||||
FS_FileExists,
|
||||
FS_AllowDirectPaths,
|
||||
|
||||
|
|
|
@ -595,9 +595,7 @@ void Cmd_TokenizeString( const char *text )
|
|||
if( cmd_argc == 1 )
|
||||
cmd_args = text;
|
||||
|
||||
host.com_ignorebracket = true;
|
||||
text = COM_ParseFile( (char*)text, cmd_token );
|
||||
host.com_ignorebracket = false;
|
||||
text = _COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL );
|
||||
|
||||
if( !text ) return;
|
||||
|
||||
|
|
|
@ -429,31 +429,6 @@ uint LZSS_Decompress( const byte *pInput, byte *pOutput )
|
|||
return totalBytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_IsSingleChar
|
||||
|
||||
interpert this character as single
|
||||
==============
|
||||
*/
|
||||
static int COM_IsSingleChar( char c )
|
||||
{
|
||||
if( c == '{' || c == '}' || c == '\'' || c == ',' )
|
||||
return true;
|
||||
|
||||
if( !host.com_ignorebracket && ( c == ')' || c == '(' ))
|
||||
return true;
|
||||
|
||||
if( host.com_handlecolon && c == ':' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_IsWhiteSpace
|
||||
|
@ -469,136 +444,6 @@ static int COM_IsWhiteSpace( char space )
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_ParseFile
|
||||
|
||||
text parser
|
||||
==============
|
||||
*/
|
||||
char *COM_ParseFileSafe( char *data, char *token, const size_t size )
|
||||
{
|
||||
int c, len;
|
||||
|
||||
if( !token || !size )
|
||||
return NULL;
|
||||
|
||||
len = 0;
|
||||
token[0] = 0;
|
||||
|
||||
if( !data )
|
||||
return NULL;
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while(( c = ((byte)*data)) <= ' ' )
|
||||
{
|
||||
if( c == 0 )
|
||||
return NULL; // end of file;
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if( c == '/' && data[1] == '/' )
|
||||
{
|
||||
while( *data && *data != '\n' )
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
// handle quoted strings specially
|
||||
if( c == '\"' )
|
||||
{
|
||||
data++;
|
||||
while( 1 )
|
||||
{
|
||||
c = (byte)*data;
|
||||
|
||||
// unexpected line end
|
||||
if( !c )
|
||||
{
|
||||
token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
data++;
|
||||
|
||||
if( c == '\\' && *data == '"' )
|
||||
{
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = (byte)*data;
|
||||
len++;
|
||||
}
|
||||
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( c == '\"' )
|
||||
{
|
||||
token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if( COM_IsSingleChar( c ))
|
||||
{
|
||||
if( size >= 2 ) // char and \0
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
token[len] = 0;
|
||||
return data + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// couldn't pass anything
|
||||
token[0] = 0;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
}
|
||||
|
||||
data++;
|
||||
c = ((byte)*data);
|
||||
|
||||
if( COM_IsSingleChar( c ))
|
||||
break;
|
||||
} while( c > 32 );
|
||||
|
||||
token[len] = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
COM_ParseFile
|
||||
|
||||
old unsafe version of ParseFile, deprecated
|
||||
only for API compatibility
|
||||
================
|
||||
*/
|
||||
char *COM_ParseFile( char *data, char *token )
|
||||
{
|
||||
return COM_ParseFileSafe( data, token, -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
COM_ParseVector
|
||||
|
|
|
@ -422,8 +422,6 @@ typedef struct host_parm_s
|
|||
qboolean stuffcmds_pending; // should execute stuff commands
|
||||
qboolean allow_cheats; // this host will allow cheating
|
||||
qboolean con_showalways; // show console always (developer and dedicated)
|
||||
qboolean com_handlecolon; // allow COM_ParseFile to handle colon as single char
|
||||
qboolean com_ignorebracket; // allow COM_ParseFile to ignore () as single char
|
||||
qboolean change_game; // initialize when game is changed
|
||||
qboolean mouse_visible; // vgui override cursor control
|
||||
qboolean shutdown_issued; // engine is shutting down
|
||||
|
@ -854,8 +852,6 @@ void CL_LegacyUpdateInfo( void );
|
|||
void CL_CharEvent( int key );
|
||||
qboolean CL_DisableVisibility( void );
|
||||
int CL_PointContents( const vec3_t point );
|
||||
char *COM_ParseFile( char *data, char *token );
|
||||
char *COM_ParseFileSafe( char *data, char *token, const size_t size );
|
||||
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength );
|
||||
int CL_GetDemoComment( const char *demoname, char *comment );
|
||||
void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName );
|
||||
|
|
|
@ -369,7 +369,6 @@ typedef struct ref_api_s
|
|||
|
||||
// filesystem
|
||||
byte* (*COM_LoadFile)( const char *path, fs_offset_t *pLength, qboolean gamedironly );
|
||||
char* (*COM_ParseFile)( char *data, char *token );
|
||||
// use Mem_Free instead
|
||||
// void (*COM_FreeFile)( void *buffer );
|
||||
int (*FS_FileExists)( const char *filename, int gamedironly );
|
||||
|
|
150
public/crtlib.c
150
public/crtlib.c
|
@ -967,6 +967,156 @@ void COM_Hex2String( uint8_t hex, char *str )
|
|||
*str = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_IsSingleChar
|
||||
|
||||
interpert this character as single
|
||||
==============
|
||||
*/
|
||||
static int COM_IsSingleChar( unsigned int flags, char c )
|
||||
{
|
||||
if( c == '{' || c == '}' || c == '\'' || c == ',' )
|
||||
return true;
|
||||
|
||||
if( !FBitSet( flags, PFILE_IGNOREBRACKET ) && ( c == ')' || c == '(' ))
|
||||
return true;
|
||||
|
||||
if( FBitSet( flags, PFILE_HANDLECOLON ) && c == ':' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_ParseFile
|
||||
|
||||
text parser
|
||||
==============
|
||||
*/
|
||||
const char *_COM_ParseFileSafe( const char *data, char *token, const int size, unsigned int flags, int *plen )
|
||||
{
|
||||
int c, len = 0;
|
||||
qboolean overflow = false;
|
||||
|
||||
if( !token || !size )
|
||||
{
|
||||
if( plen ) *plen = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token[0] = 0;
|
||||
|
||||
if( !data )
|
||||
return NULL;
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while(( c = ((byte)*data)) <= ' ' )
|
||||
{
|
||||
if( c == 0 )
|
||||
{
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
return NULL; // end of file;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if( c == '/' && data[1] == '/' )
|
||||
{
|
||||
while( *data && *data != '\n' )
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
// handle quoted strings specially
|
||||
if( c == '\"' )
|
||||
{
|
||||
data++;
|
||||
while( 1 )
|
||||
{
|
||||
c = (byte)*data;
|
||||
|
||||
// unexpected line end
|
||||
if( !c )
|
||||
{
|
||||
token[len] = 0;
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
return data;
|
||||
}
|
||||
data++;
|
||||
|
||||
if( c == '\\' && *data == '"' )
|
||||
{
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = (byte)*data;
|
||||
len++;
|
||||
}
|
||||
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( c == '\"' )
|
||||
{
|
||||
token[len] = 0;
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
return data;
|
||||
}
|
||||
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if( COM_IsSingleChar( flags, c ))
|
||||
{
|
||||
if( size >= 2 ) // char and \0
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
token[len] = 0;
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
return data + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// couldn't pass anything
|
||||
token[0] = 0;
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
if( len + 1 < size )
|
||||
{
|
||||
token[len] = c;
|
||||
len++;
|
||||
}
|
||||
|
||||
data++;
|
||||
c = ((byte)*data);
|
||||
|
||||
if( COM_IsSingleChar( flags, c ))
|
||||
break;
|
||||
} while( c > 32 );
|
||||
|
||||
token[len] = 0;
|
||||
|
||||
if( plen ) *plen = overflow ? -1 : len;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive )
|
||||
{
|
||||
return matchpattern_with_separator( in, pattern, caseinsensitive, "/\\:", false );
|
||||
|
|
|
@ -38,6 +38,12 @@ enum
|
|||
TIME_FILENAME,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PFILE_IGNOREBRACKET = BIT( 0 ),
|
||||
PFILE_HANDLECOLON = BIT( 1 )
|
||||
};
|
||||
|
||||
//
|
||||
// crtlib.c
|
||||
//
|
||||
|
@ -89,6 +95,9 @@ char COM_Hex2Char( uint8_t hex );
|
|||
void COM_Hex2String( uint8_t hex, char *str );
|
||||
#define COM_CheckString( string ) ( ( !string || !*string ) ? 0 : 1 )
|
||||
#define COM_CheckStringEmpty( string ) ( ( !*string ) ? 0 : 1 )
|
||||
const char *_COM_ParseFileSafe( const char *data, char *token, const int size, unsigned int flags, int *len );
|
||||
#define COM_ParseFileSafe( data, token, size ) _COM_ParseFileSafe( data, token, size, 0, NULL )
|
||||
#define COM_ParseFile( data, token ) COM_ParseFileSafe( data, token, -1 )
|
||||
int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive );
|
||||
int matchpattern_with_separator( const char *in, const char *pattern, qboolean caseinsensitive, const char *separators, qboolean wildcard_least_one );
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ static void R_ParseDetailTextures( const char *filename )
|
|||
pfile = (char *)afile;
|
||||
|
||||
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
||||
while(( pfile = gEngfuncs.COM_ParseFile( pfile, token )) != NULL )
|
||||
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
|
||||
{
|
||||
texname[0] = '\0';
|
||||
detail_texname[0] = '\0';
|
||||
|
@ -45,26 +45,26 @@ static void R_ParseDetailTextures( const char *filename )
|
|||
{
|
||||
// NOTE: COM_ParseFile handled some symbols seperately
|
||||
// this code will be fix it
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
pfile = COM_ParseFile( pfile, token );
|
||||
Q_strncat( texname, "{", sizeof( texname ));
|
||||
Q_strncat( texname, token, sizeof( texname ));
|
||||
}
|
||||
else Q_strncpy( texname, token, sizeof( texname ));
|
||||
|
||||
// read detailtexture name
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
pfile = COM_ParseFile( pfile, token );
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
|
||||
// trying the scales or '{'
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
pfile = COM_ParseFile( pfile, token );
|
||||
|
||||
// read second part of detailtexture name
|
||||
if( token[0] == '{' )
|
||||
{
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // read scales
|
||||
pfile = COM_ParseFile( pfile, token ); // read scales
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // parse scales
|
||||
pfile = COM_ParseFile( pfile, token ); // parse scales
|
||||
}
|
||||
|
||||
Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname );
|
||||
|
@ -72,7 +72,7 @@ static void R_ParseDetailTextures( const char *filename )
|
|||
// read scales
|
||||
xScale = Q_atof( token );
|
||||
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
pfile = COM_ParseFile( pfile, token );
|
||||
yScale = Q_atof( token );
|
||||
|
||||
if( xScale <= 0.0f || yScale <= 0.0f )
|
||||
|
|
Loading…
Reference in New Issue