]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - fs.c
Cleaned up alot more memory leaks. (still get 720 leaks just running demo1.dem)
[xonotic/darkplaces.git] / fs.c
diff --git a/fs.c b/fs.c
index 258e8a77c1fdbb63f31f87448e77d1784d3c042a..376336b7cf199156d526464c2faa6306dd659089 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -354,6 +354,8 @@ qboolean PK3_OpenLibrary (void)
 
 #ifdef WIN32
        dllname = "zlib.dll";
+#elif defined(MACOSX)
+       dllname = "libz.dylib";
 #else
        dllname = "libz.so";
 #endif
@@ -405,10 +407,10 @@ qboolean PK3_GetEndOfCentralDir (const char *packfile, FILE *packhandle, pk3_end
        buffer = Mem_Alloc (tempmempool, maxsize);
 #ifdef FS_USESYSCALLS
        lseek (packhandle, filesize - maxsize, SEEK_SET);
-       if (read (packhandle, buffer, maxsize) != (unsigned long) maxsize)
+       if (read (packhandle, buffer, maxsize) != (ssize_t) maxsize)
 #else
        fseek (packhandle, filesize - maxsize, SEEK_SET);
-       if (fread (buffer, 1, maxsize, packhandle) != (unsigned long) maxsize)
+       if (fread (buffer, 1, maxsize, packhandle) != (size_t) maxsize)
 #endif
        {
                Mem_Free (buffer);
@@ -543,7 +545,9 @@ int PK3_BuildFileList (pack_t *pack, const pk3_endOfCentralDir_t *eocd)
                remaining -= count;
        }
 
-       Mem_Free (central_dir);
+       // If the package is empty, central_dir is NULL here
+       if (central_dir != NULL)
+               Mem_Free (central_dir);
        return pack->numfiles;
 }
 
@@ -602,7 +606,7 @@ pack_t *FS_LoadPackPK3 (const char *packfile)
        packlist = pack;
 
        real_nb_files = PK3_BuildFileList (pack, &eocd);
-       if (real_nb_files <= 0)
+       if (real_nb_files < 0)
                Sys_Error ("%s is not a valid PK3 file", packfile);
 
        Con_Printf("Added packfile %s (%i files)\n", packfile, real_nb_files);
@@ -665,28 +669,29 @@ static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
                                                                         size_t realsize, file_flags_t flags)
 {
        int (*strcmp_funct) (const char* str1, const char* str2);
-       size_t left, right, middle;
-       int diff;
+       int left, right, middle;
        packfile_t *file;
 
        strcmp_funct = pack->ignorecase ? strcasecmp : strcmp;
 
        // Look for the slot we should put that file into (binary search)
        left = 0;
-       right = pack->numfiles;
-       while (left != right)
+       right = pack->numfiles - 1;
+       while (left <= right)
        {
-               middle = (left + right - 1) / 2;
+               int diff;
+
+               middle = (left + right) / 2;
                diff = strcmp_funct (pack->files[middle].name, name);
 
                // If we found the file, there's a problem
                if (!diff)
-                       Sys_Error ("Package %s contains several time the file %s\n",
+                       Sys_Error ("Package %s contains the file %s several times\n",
                                           pack->filename, name);
 
                // If we're too far in the list
                if (diff > 0)
-                       right = middle;
+                       right = middle - 1;
                else
                        left = middle + 1;
        }
@@ -1030,8 +1035,22 @@ void FS_Init (void)
                        Cvar_SetQuick (&scr_screenshot_name, com_modname);
                }
        }
+
+       // If "-condebug" is in the command line, remove the previous log file
+       if (COM_CheckParm ("-condebug") != 0)
+               unlink (va("%s/qconsole.log", fs_gamedir));
 }
 
+/*
+================
+FS_Shutdown
+================
+*/
+void FS_Shutdown (void)
+{
+       Mem_FreePool (&pak_mempool);
+       Mem_FreePool (&fs_mempool);
+}
 
 /*
 ====================
@@ -1121,6 +1140,39 @@ qfile_t *FS_OpenRead (const char *path, int offs, int len)
        return file;
 }
 
+/*
+====================
+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.
+====================
+*/
+int FS_CheckNastyPath (const char *path)
+{
+       // Windows: don't allow \ in filenames (windows-only), period.
+       // (on Windows \ is a directory separator, but / is also supported)
+       if (strstr(path, "\\"))
+               return 1; // non-portable
+       // 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 (strstr(path, ":"))
+               return 1; // non-portable attempt to go to root of drive
+       // Amiga: // is parent directory
+       if (strstr(path, "//"))
+               return 1; // non-portable attempt to go to parent directory
+       // all: don't allow going to current directory (./) or parent directory (../ or /../)
+       if (strstr(path, "./"))
+               return 2; // attempt to go to parent directory
+       // after all these checks we're pretty sure it's a / separated filename
+       // and won't do much if any harm
+       return false;
+}
+
 
 /*
 ====================
@@ -1136,7 +1188,6 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet)
 {
        searchpath_t *search;
        pack_t *pak;
-       int (*strcmp_funct) (const char* str1, const char* str2);
 
        // search through the path, one element at a time
        for (search = fs_searchpaths;search;search = search->next)
@@ -1144,26 +1195,27 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet)
                // is the element a pak file?
                if (search->pack)
                {
-                       size_t left, right, middle;
+                       int (*strcmp_funct) (const char* str1, const char* str2);
+                       int left, right, middle;
 
                        pak = search->pack;
                        strcmp_funct = pak->ignorecase ? strcasecmp : strcmp;
 
                        // Look for the file (binary search)
                        left = 0;
-                       right = pak->numfiles;
-                       while (left != right)
+                       right = pak->numfiles - 1;
+                       while (left <= right)
                        {
                                int diff;
 
-                               middle = (left + right - 1) / 2;
+                               middle = (left + right) / 2;
                                diff = strcmp_funct (pak->files[middle].name, name);
 
                                // Found it
                                if (!diff)
                                {
                                        if (!quiet)
-                                               Sys_Printf("FS_FindFile: %s in %s\n",
+                                               Con_DPrintf("FS_FindFile: %s in %s\n",
                                                                        pak->files[middle].name, pak->filename);
 
                                        if (index != NULL)
@@ -1173,7 +1225,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet)
 
                                // If we're too far in the list
                                if (diff > 0)
-                                       right = middle;
+                                       right = middle - 1;
                                else
                                        left = middle + 1;
                        }
@@ -1185,7 +1237,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet)
                        if (FS_SysFileExists (netpath))
                        {
                                if (!quiet)
-                                       Sys_Printf("FS_FindFile: %s\n", netpath);
+                                       Con_DPrintf("FS_FindFile: %s\n", netpath);
 
                                if (index != NULL)
                                        *index = -1;
@@ -1195,7 +1247,7 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet)
        }
 
        if (!quiet)
-               Sys_Printf("FS_FindFile: can't find %s\n", name);
+               Con_DPrintf("FS_FindFile: can't find %s\n", name);
 
        if (index != NULL)
                *index = -1;
@@ -1312,6 +1364,12 @@ Open a file. The syntax is the same as fopen
 */
 qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet)
 {
+       if (FS_CheckNastyPath(filepath))
+       {
+               Con_Printf("FS_Open(\"%s\", \"%s\", %s): nasty filename rejected\n", filepath, mode, quiet ? "true" : "false");
+               return NULL;
+       }
+
        // If the file is opened in "write" or "append" mode
        if (strchr (mode, 'w') || strchr (mode, 'a'))
        {
@@ -1626,7 +1684,11 @@ int FS_Seek (qfile_t* file, long offset, int whence)
        // Quick path for unpacked files
        if (! (file->flags & FS_FLAG_PACKED))
 #ifdef FS_USESYSCALLS
-               return lseek (file->stream, offset, whence);
+       {
+               if (lseek (file->stream, offset, whence) == -1)
+                       return -1;
+               return 0;
+       }
 #else
                return fseek (file->stream, offset, whence);
 #endif
@@ -2105,7 +2167,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
                                                        if (liststart == NULL)
                                                                liststart = listcurrent;
                                                        if (!quiet)
-                                                               Sys_Printf("SearchPackFile: %s : %s\n", pak->filename, temp);
+                                                               Con_DPrintf("SearchPackFile: %s : %s\n", pak->filename, temp);
                                                }
                                        }
                                        // strip off one path element at a time until empty
@@ -2144,7 +2206,7 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet)
                                                        if (liststart == NULL)
                                                                liststart = listcurrent;
                                                        if (!quiet)
-                                                               Sys_Printf("SearchDirFile: %s\n", temp);
+                                                               Con_DPrintf("SearchDirFile: %s\n", temp);
                                                }
                                        }
                                }