diff --git a/include/QF/gib_builtin.h b/include/QF/gib_builtin.h index 292804bb0..0d39ac9ce 100644 --- a/include/QF/gib_builtin.h +++ b/include/QF/gib_builtin.h @@ -51,4 +51,4 @@ void GIB_Arg_Strip_Delim (unsigned int arg); void GIB_Return (const char *str); void GIB_Builtin_Add (const char *name, void (*func) (void), enum gib_builtin_type_e type); gib_builtin_t *GIB_Builtin_Find (const char *name); -void GIB_Builtin_Init (void); +void GIB_Builtin_Init (qboolean sandbox); diff --git a/include/QF/gib_init.h b/include/QF/gib_init.h index bd7020933..d6e4189e5 100644 --- a/include/QF/gib_init.h +++ b/include/QF/gib_init.h @@ -29,4 +29,4 @@ $Id$ */ -void GIB_Init (void); +void GIB_Init (qboolean sandbox); diff --git a/include/QF/sys.h b/include/QF/sys.h index 0c2c22ae0..c86ca25d9 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -44,8 +44,15 @@ extern struct cvar_s *developer; extern const char sys_char_map[256]; +enum e_pathtype { + PATHTYPE_ABSOLUTE, + PATHTYPE_RELATIVE_ABOVE, + PATHTYPE_RELATIVE_BELOW +}; + int Sys_FileTime (const char *path); void Sys_mkdir (const char *path); +enum e_pathtype Sys_PathType (const char *path); typedef void (*sys_printf_t) (const char *fmt, va_list args); diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 56576662a..e7f84b6b5 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -522,6 +522,23 @@ GIB_Thread_Kill_f (void) /* File access */ +int (*GIB_File_Transform_Path) (dstring_t *path) = NULL; + +int +GIB_File_Transform_Path_Null (dstring_t *path) +{ + return 0; +} + +int +GIB_File_Transform_Path_Secure (dstring_t *path) +{ + if (Sys_PathType (path->str) != PATHTYPE_RELATIVE_BELOW) + return -1; + dstring_insertstr (path, 0, com_gamedir); + return 0; +} + void GIB_File_Read_f (void) { @@ -534,27 +551,26 @@ GIB_File_Read_f (void) "usage: file::read path_and_filename"); return; } - path = COM_CompressPath (GIB_Argv (1)); - if (!path[0]) { + if (!*GIB_Argv (1)) { Cbuf_Error ("file", "file::read: null filename provided"); return; } - if (path[0] == '/' || (path[0] == '.' && path[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(1))) { Cbuf_Error ("access", - "file::read: access to %s denied", path); + "file::read: access to %s denied", GIB_Argv(1)); return; } + path = GIB_Argv (1); mark = Hunk_LowMark (); contents = (char *) COM_LoadHunkFile (path); if (!contents) { Cbuf_Error ("file", - "file::read: could not open %s/%s for reading: %s", com_gamedir, path, strerror (errno)); + "file::read: could not open %s for reading: %s", path, strerror (errno)); return; } GIB_Return (contents); Hunk_FreeToLowMark (mark); - free (path); } void @@ -569,25 +585,24 @@ GIB_File_Write_f (void) "usage: file::write path_and_filename data"); return; } - path = COM_CompressPath (GIB_Argv (1)); - if (!path[0]) { + if (!*GIB_Argv(1)) { Cbuf_Error ("file", "file::write: null filename provided"); return; } - if (path[0] == '/' || (path[0] == '.' && path[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(1))) { Cbuf_Error ("access", - "file::write: access to %s denied", path); + "file::write: access to %s denied", GIB_Argv(1)); return; } - if (!(file = Qopen (va ("%s/%s", com_gamedir, path), "w"))) { + path = GIB_Argv(1); + if (!(file = Qopen (path, "w"))) { Cbuf_Error ("file", - "file::write: could not open %s/%s for writing: %s", com_gamedir, path, strerror (errno)); + "file::write: could not open %s for writing: %s", path, strerror (errno)); return; } Qprintf (file, "%s", GIB_Argv (2)); Qclose (file); - free (path); } void @@ -605,23 +620,23 @@ GIB_File_Find_f (void) "usage: file::find glob [path]"); return; } - path = COM_CompressPath (GIB_Argv (2)); if (GIB_Argc () == 3) { - if (!path[0]) { + if (!*GIB_Argv(2)) { Cbuf_Error ("file", "file::find: null path provided"); return; } - if (path[0] == '/' || (path[0] == '.' && path[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(2))) { Cbuf_Error ("access", - "file::find: access to %s denied", path); + "file::find: access to %s denied", GIB_Argv(2)); return; } } - directory = opendir (va ("%s/%s", com_gamedir, path)); + path = GIB_Argv(2); + directory = opendir (path); if (!directory) { Cbuf_Error ("file", - "file.find: could not open directory %s/%s: %s", com_gamedir, path, strerror (errno)); + "file.find: could not open directory %s: %s", path, strerror (errno)); return; } list = dstring_newstr (); @@ -640,14 +655,12 @@ GIB_File_Find_f (void) else GIB_Return (""); dstring_delete (list); - free (path); } void GIB_File_Move_f (void) { char *path1, *path2; - dstring_t *from, *to; if (GIB_Argc () != 3) { Cbuf_Error ("syntax", @@ -655,30 +668,22 @@ GIB_File_Move_f (void) "usage: file::move from_file to_file"); return; } - path1 = COM_CompressPath (GIB_Argv (1)); - path2 = COM_CompressPath (GIB_Argv (2)); - if (path1[0] == '/' || (path1[0] == '.' && path1[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(1))) { Cbuf_Error ("access", - "file::move: access to %s denied", path1); + "file::move: access to %s denied", GIB_Argv(1)); return; } - if (path2[0] == '/' || (path2[0] == '.' && path2[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(2))) { Cbuf_Error ("access", - "file::move: access to %s denied", path2); + "file::move: access to %s denied", GIB_Argv(2)); return; } - from = dstring_newstr (); - to = dstring_newstr (); - dsprintf (from, "%s/%s", com_gamedir, path1); - dsprintf (to, "%s/%s", com_gamedir, path2); - if (Qrename (from->str, to->str)) + path1 = GIB_Argv(1); + path2 = GIB_Argv(2); + if (Qrename (path1, path2)) Cbuf_Error ("file", "file::move: could not move %s to %s: %s", - from->str, to->str, strerror(errno)); - dstring_delete (from); - dstring_delete (to); - free (path1); - free (path2); + path1, path2, strerror(errno)); } void @@ -692,17 +697,16 @@ GIB_File_Delete_f (void) "usage: file::delete file"); return; } - path = COM_CompressPath (GIB_Argv (1)); - if (path[0] == '/' || (path[0] == '.' && path[1] == '.')) { + if (GIB_File_Transform_Path (GIB_Argd(1))) { Cbuf_Error ("access", - "file::delete: access to %s denied", path); + "file::delete: access to %s denied", GIB_Argv(1)); return; } - if (Qremove(va("%s/%s", com_gamedir, path))) + path = GIB_Argv (1); + if (Qremove(path)) Cbuf_Error ("file", - "file::delete: could not delete %s/%s: %s", - com_gamedir, path, strerror(errno)); - free (path); + "file::delete: could not delete %s: %s", + path, strerror(errno)); } void @@ -750,10 +754,15 @@ GIB_Print_f (void) } void -GIB_Builtin_Init (void) +GIB_Builtin_Init (qboolean sandbox) { gib_globals = Hash_NewTable (512, GIB_Var_Get_Key, GIB_Var_Free, 0); + if (sandbox) + GIB_File_Transform_Path = GIB_File_Transform_Path_Secure; + else + GIB_File_Transform_Path = GIB_File_Transform_Path_Null; + GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("function::get", GIB_Function_Get_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("function::export", GIB_Function_Export_f, GIB_BUILTIN_NORMAL); diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index 23b74486f..cfdc29e8e 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -76,7 +76,7 @@ GIB_Exec_Override_f (void) { } void -GIB_Init (void) +GIB_Init (qboolean sandbox) { // Override the exec command with a GIB-aware one if (Cmd_Exists("exec")) { @@ -84,5 +84,5 @@ GIB_Init (void) Cmd_AddCommand ("exec", GIB_Exec_Override_f, "Execute a script file."); } // Initialize builtins - GIB_Builtin_Init (); + GIB_Builtin_Init (sandbox); } diff --git a/libs/util/sys.c b/libs/util/sys.c index 5b427defc..5d1cf1e6b 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -67,6 +67,7 @@ static const char rcsid[] = #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/sys.h" +#include "QF/quakefs.h" #include "compat.h" @@ -180,6 +181,24 @@ Sys_FileTime (const char *path) return -1; } +enum e_pathtype +Sys_PathType (const char *path) +{ + enum e_pathtype type; + char *comp = COM_CompressPath (path); + if (comp[0] == '/' +#ifdef WIN32 + || (comp[0] && comp[1] == ':') +#endif /* WIN32 */ + ) + type = PATHTYPE_ABSOLUTE; + else if (comp[0] == '.' && comp[1] == '.') + type = PATHTYPE_RELATIVE_ABOVE; + else + type = PATHTYPE_RELATIVE_BELOW; + free (comp); + return type; +} /* Sys_SetPrintf diff --git a/nq/source/host.c b/nq/source/host.c index d1e7e97dc..8c903735d 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -867,7 +867,7 @@ Host_Init (void) Sys_Init (); Cmd_Init (); - GIB_Init (); + GIB_Init (true); // execute +set as early as possible Cmd_StuffCmds (host_cbuf); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 82cbcb7d6..66f2a9514 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1671,7 +1671,7 @@ Host_Init (void) Sys_Init (); Cmd_Init (); - GIB_Init (); + GIB_Init (true); // execute +set as early as possible Cmd_StuffCmds (cl_cbuf); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index ee275f381..6c6554747 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2470,7 +2470,7 @@ SV_Init (void) Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); Cmd_Init (); - GIB_Init (); + GIB_Init (true); // execute +set as early as possible Cmd_StuffCmds (sv_cbuf); diff --git a/tools/carne/main.c b/tools/carne/main.c index 525bb0af2..eb77b9a8e 100644 --- a/tools/carne/main.c +++ b/tools/carne/main.c @@ -31,7 +31,7 @@ int main (int argc, char **argv) Cvar_Init_Hash (); Cmd_Init_Hash (); Cmd_Init (); - GIB_Init (); + GIB_Init (false); // No sandbox // Load the script file = Qopen (argv[1], "r");