#ifdef WIN32
dllname = "zlib.dll";
+#elif defined(MACOSX)
+ dllname = "libz.dylib";
#else
dllname = "libz.so";
#endif
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);
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;
}
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);
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;
}
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));
}
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;
+}
+
/*
====================
{
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)
// 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)
// If we're too far in the list
if (diff > 0)
- right = middle;
+ right = middle - 1;
else
left = middle + 1;
}
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;
}
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;
*/
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'))
{
// 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
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
if (liststart == NULL)
liststart = listcurrent;
if (!quiet)
- Sys_Printf("SearchDirFile: %s\n", temp);
+ Con_DPrintf("SearchDirFile: %s\n", temp);
}
}
}