mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-01-30 16:54:29 +00:00
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;
|
char *out;
|
||||||
|
|
||||||
host.com_handlecolon = true;
|
out = _COM_ParseFileSafe( data, token, -1, PFILE_HANDLECOLON, NULL );
|
||||||
out = COM_ParseFile( data, token );
|
|
||||||
host.com_handlecolon = false;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -1106,6 +1106,17 @@ static void GAME_EXPORT UI_ShellExecute( const char *path, const char *parms, in
|
|||||||
Sys_Quit();
|
Sys_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
pfnParseFile
|
||||||
|
|
||||||
|
legacy wrapper
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
static char *pfnParseFile( char *buf, char *token )
|
||||||
|
{
|
||||||
|
return COM_ParseFile( buf, token );
|
||||||
|
}
|
||||||
|
|
||||||
// engine callbacks
|
// engine callbacks
|
||||||
static ui_enginefuncs_t gEngfuncs =
|
static ui_enginefuncs_t gEngfuncs =
|
||||||
@ -1159,7 +1170,7 @@ static ui_enginefuncs_t gEngfuncs =
|
|||||||
CL_Active,
|
CL_Active,
|
||||||
pfnClientJoin,
|
pfnClientJoin,
|
||||||
COM_LoadFileForMe,
|
COM_LoadFileForMe,
|
||||||
COM_ParseFile,
|
pfnParseFile,
|
||||||
COM_FreeFile,
|
COM_FreeFile,
|
||||||
Key_ClearStates,
|
Key_ClearStates,
|
||||||
Key_SetKeyDest,
|
Key_SetKeyDest,
|
||||||
|
@ -861,9 +861,7 @@ void CL_QuakeExecStuff( void )
|
|||||||
|
|
||||||
if( !*text ) break;
|
if( !*text ) break;
|
||||||
|
|
||||||
host.com_ignorebracket = true;
|
text = _COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL );
|
||||||
text = COM_ParseFile( text, token );
|
|
||||||
host.com_ignorebracket = false;
|
|
||||||
|
|
||||||
if( !text ) break;
|
if( !text ) break;
|
||||||
|
|
||||||
|
@ -335,7 +335,6 @@ static ref_api_t gEngfuncs =
|
|||||||
COM_GetProcAddress,
|
COM_GetProcAddress,
|
||||||
|
|
||||||
FS_LoadFile,
|
FS_LoadFile,
|
||||||
COM_ParseFile,
|
|
||||||
FS_FileExists,
|
FS_FileExists,
|
||||||
FS_AllowDirectPaths,
|
FS_AllowDirectPaths,
|
||||||
|
|
||||||
|
@ -595,9 +595,7 @@ void Cmd_TokenizeString( const char *text )
|
|||||||
if( cmd_argc == 1 )
|
if( cmd_argc == 1 )
|
||||||
cmd_args = text;
|
cmd_args = text;
|
||||||
|
|
||||||
host.com_ignorebracket = true;
|
text = _COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL );
|
||||||
text = COM_ParseFile( (char*)text, cmd_token );
|
|
||||||
host.com_ignorebracket = false;
|
|
||||||
|
|
||||||
if( !text ) return;
|
if( !text ) return;
|
||||||
|
|
||||||
|
@ -429,31 +429,6 @@ uint LZSS_Decompress( const byte *pInput, byte *pOutput )
|
|||||||
return totalBytes;
|
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
|
COM_IsWhiteSpace
|
||||||
@ -469,136 +444,6 @@ static int COM_IsWhiteSpace( char space )
|
|||||||
return 0;
|
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
|
COM_ParseVector
|
||||||
|
@ -422,8 +422,6 @@ typedef struct host_parm_s
|
|||||||
qboolean stuffcmds_pending; // should execute stuff commands
|
qboolean stuffcmds_pending; // should execute stuff commands
|
||||||
qboolean allow_cheats; // this host will allow cheating
|
qboolean allow_cheats; // this host will allow cheating
|
||||||
qboolean con_showalways; // show console always (developer and dedicated)
|
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 change_game; // initialize when game is changed
|
||||||
qboolean mouse_visible; // vgui override cursor control
|
qboolean mouse_visible; // vgui override cursor control
|
||||||
qboolean shutdown_issued; // engine is shutting down
|
qboolean shutdown_issued; // engine is shutting down
|
||||||
@ -854,8 +852,6 @@ void CL_LegacyUpdateInfo( void );
|
|||||||
void CL_CharEvent( int key );
|
void CL_CharEvent( int key );
|
||||||
qboolean CL_DisableVisibility( void );
|
qboolean CL_DisableVisibility( void );
|
||||||
int CL_PointContents( const vec3_t point );
|
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 );
|
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength );
|
||||||
int CL_GetDemoComment( const char *demoname, char *comment );
|
int CL_GetDemoComment( const char *demoname, char *comment );
|
||||||
void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName );
|
void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName );
|
||||||
|
@ -369,7 +369,6 @@ typedef struct ref_api_s
|
|||||||
|
|
||||||
// filesystem
|
// filesystem
|
||||||
byte* (*COM_LoadFile)( const char *path, fs_offset_t *pLength, qboolean gamedironly );
|
byte* (*COM_LoadFile)( const char *path, fs_offset_t *pLength, qboolean gamedironly );
|
||||||
char* (*COM_ParseFile)( char *data, char *token );
|
|
||||||
// use Mem_Free instead
|
// use Mem_Free instead
|
||||||
// void (*COM_FreeFile)( void *buffer );
|
// void (*COM_FreeFile)( void *buffer );
|
||||||
int (*FS_FileExists)( const char *filename, int gamedironly );
|
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';
|
*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 )
|
int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive )
|
||||||
{
|
{
|
||||||
return matchpattern_with_separator( in, pattern, caseinsensitive, "/\\:", false );
|
return matchpattern_with_separator( in, pattern, caseinsensitive, "/\\:", false );
|
||||||
|
@ -38,6 +38,12 @@ enum
|
|||||||
TIME_FILENAME,
|
TIME_FILENAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PFILE_IGNOREBRACKET = BIT( 0 ),
|
||||||
|
PFILE_HANDLECOLON = BIT( 1 )
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// crtlib.c
|
// crtlib.c
|
||||||
//
|
//
|
||||||
@ -89,6 +95,9 @@ char COM_Hex2Char( uint8_t hex );
|
|||||||
void COM_Hex2String( uint8_t hex, char *str );
|
void COM_Hex2String( uint8_t hex, char *str );
|
||||||
#define COM_CheckString( string ) ( ( !string || !*string ) ? 0 : 1 )
|
#define COM_CheckString( string ) ( ( !string || !*string ) ? 0 : 1 )
|
||||||
#define COM_CheckStringEmpty( 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( 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 );
|
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;
|
pfile = (char *)afile;
|
||||||
|
|
||||||
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
||||||
while(( pfile = gEngfuncs.COM_ParseFile( pfile, token )) != NULL )
|
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
|
||||||
{
|
{
|
||||||
texname[0] = '\0';
|
texname[0] = '\0';
|
||||||
detail_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
|
// NOTE: COM_ParseFile handled some symbols seperately
|
||||||
// this code will be fix it
|
// 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, "{", sizeof( texname ));
|
||||||
Q_strncat( texname, token, sizeof( texname ));
|
Q_strncat( texname, token, sizeof( texname ));
|
||||||
}
|
}
|
||||||
else Q_strncpy( texname, token, sizeof( texname ));
|
else Q_strncpy( texname, token, sizeof( texname ));
|
||||||
|
|
||||||
// read detailtexture name
|
// read detailtexture name
|
||||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
pfile = COM_ParseFile( pfile, token );
|
||||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||||
|
|
||||||
// trying the scales or '{'
|
// trying the scales or '{'
|
||||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
pfile = COM_ParseFile( pfile, token );
|
||||||
|
|
||||||
// read second part of detailtexture name
|
// read second part of detailtexture name
|
||||||
if( token[0] == '{' )
|
if( token[0] == '{' )
|
||||||
{
|
{
|
||||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
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 ));
|
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 );
|
Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname );
|
||||||
@ -72,7 +72,7 @@ static void R_ParseDetailTextures( const char *filename )
|
|||||||
// read scales
|
// read scales
|
||||||
xScale = Q_atof( token );
|
xScale = Q_atof( token );
|
||||||
|
|
||||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
pfile = COM_ParseFile( pfile, token );
|
||||||
yScale = Q_atof( token );
|
yScale = Q_atof( token );
|
||||||
|
|
||||||
if( xScale <= 0.0f || yScale <= 0.0f )
|
if( xScale <= 0.0f || yScale <= 0.0f )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user