public: add CheckNastyPath from Darkplaces's VFS so it can be used in engine for path traversal checks

This commit is contained in:
Alibek Omarov
2026-05-16 21:28:51 +05:00
parent 8120669e5b
commit 5d7ed9d8a7
3 changed files with 48 additions and 37 deletions

View File

@@ -555,48 +555,16 @@ void FS_ClearSearchPath( void )
}
}
/*
====================
FS_CheckNastyPath
Return true if the path should be rejected due to one of the following:
1: path elements that are non-portable
2: path elements that would allow access to files outside the game directory,
or are just not a good idea for a mod to be using.
====================
*/
static int FS_CheckNastyPath( const char *path )
{
// all: never allow an empty path, as for gamedir it would access the parent directory and a non-gamedir path it is just useless
if( COM_StringEmptyOrNULL( path )) return 2;
if( COM_StringEmptyOrNULL( path ))
return 2;
if( fs_ext_path ) return 0; // allow any path
if( fs_ext_path )
return 0; // allow any path
// Mac: don't allow Mac-only filenames - : is a directory separator
// instead of /, but we rely on / working already, so there's no reason to
// support a Mac-only path
// Amiga and Windows: : tries to go to root of drive
if( Q_strchr( path, ':' )) return 1; // non-portable attempt to go to root of drive
// Amiga: // is parent directory
if( Q_strstr( path, "//")) return 1; // non-portable attempt to go to parent directory
// all: don't allow going to parent directory (../ or /../)
if( Q_strstr( path, "..")) return 2; // attempt to go outside the game directory
// Windows and UNIXes: don't allow absolute paths
if( path[0] == '/') return 2; // attempt to go outside the game directory
#if 0
// all: forbid trailing slash on gamedir
if( isgamedir && path[Q_strlen(path)-1] == '/' ) return 2;
#endif
// all: forbid leading dot on any filename for any reason
if( Q_strstr(path, "/.")) return 2; // attempt to go outside the game directory
// after all these checks we're pretty sure it's a / separated filename
// and won't do much if any harm
return false;
return COM_CheckNastyPath( path );
}
/*

View File

@@ -666,6 +666,48 @@ void COM_PathSlashFix( char *path )
}
}
/*
====================
COM_CheckNastyPath
Return true if the path should be rejected due to one of the following:
1: path elements that are non-portable
2: path elements that would allow access to files outside the game directory,
or are just not a good idea for a mod to be using.
====================
*/
int COM_CheckNastyPath( const char *path )
{
// all: never allow an empty path, as for gamedir it would access the parent directory and a non-gamedir path it is just useless
if( COM_StringEmptyOrNULL( path )) return 2;
// Mac: don't allow Mac-only filenames - : is a directory separator
// instead of /, but we rely on / working already, so there's no reason to
// support a Mac-only path
// Amiga and Windows: : tries to go to root of drive
if( Q_strchr( path, ':' )) return 1; // non-portable attempt to go to root of drive
// Amiga: // is parent directory
if( Q_strstr( path, "//")) return 1; // non-portable attempt to go to parent directory
// all: don't allow going to parent directory (../ or /../)
if( Q_strstr( path, "..")) return 2; // attempt to go outside the game directory
// Windows and UNIXes: don't allow absolute paths
if( path[0] == '/') return 2; // attempt to go outside the game directory
#if 0
// all: forbid trailing slash on gamedir
if( isgamedir && path[Q_strlen(path)-1] == '/' ) return 2;
#endif
// all: forbid leading dot on any filename for any reason
if( Q_strstr(path, "/.")) return 2; // attempt to go outside the game directory
// after all these checks we're pretty sure it's a / separated filename
// and won't do much if any harm
return false;
}
/*
==============
COM_IsSingleChar

View File

@@ -122,6 +122,7 @@ void COM_StripExtension( char *path );
void COM_RemoveLineFeed( char *str, size_t bufsize );
void COM_PathSlashFix( char *path );
void COM_TrimSpace( char *dst, const char *src, size_t size );
int COM_CheckNastyPath( const char *path );
// returns true on empty or NULL string, false otherwise
#define COM_StringEmpty( string ) (( string )[0] ? false : true )