Don't try to clean up .. segments in fteqcc's include paths. Its buggy, and doesn't handle symlink weirdness properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5805 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-02-08 10:59:53 +00:00
parent 193d14a931
commit e26f26e170
2 changed files with 28 additions and 51 deletions

View file

@ -9,7 +9,7 @@
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
void QCC_Canonicalize(char *fullname, size_t fullnamesize, const char *newfile, const char *base); void QCC_JoinPaths(char *fullname, size_t fullnamesize, const char *newfile, const char *base);
//package formats: //package formats:
//pakzip - files are uncompressed, with both a pak header and a zip trailer, allowing it to be read as either type of file. //pakzip - files are uncompressed, with both a pak header and a zip trailer, allowing it to be read as either type of file.
@ -376,7 +376,7 @@ static void PKG_CreateOutput(struct pkgctx_s *ctx, struct dataset_s *s, const ch
memset(o, 0, sizeof(*o)); memset(o, 0, sizeof(*o));
strcpy(o->code, code); strcpy(o->code, code);
o->usediffs = diff; o->usediffs = diff;
QCC_Canonicalize(o->filename, sizeof(o->filename), path, ctx->gamepath); QCC_JoinPaths(o->filename, sizeof(o->filename), path, ctx->gamepath);
o->next = s->outputs; o->next = s->outputs;
s->outputs = o; s->outputs = o;
@ -679,7 +679,7 @@ static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const cha
char basepath[MAX_OSPATH], tmppath[MAX_OSPATH]; char basepath[MAX_OSPATH], tmppath[MAX_OSPATH];
struct stat statbuf; struct stat statbuf;
QCC_Canonicalize(basepath, sizeof(basepath), fname, ctx->sourcepath); QCC_JoinPaths(basepath, sizeof(basepath), fname, ctx->sourcepath);
QC_strlcat(basepath, "/", sizeof(basepath)); QC_strlcat(basepath, "/", sizeof(basepath));
dir = opendir(basepath); dir = opendir(basepath);
if (!dir) if (!dir)
@ -691,8 +691,8 @@ static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const cha
{ {
if (*ent->d_name == '.') if (*ent->d_name == '.')
continue; continue;
QCC_Canonicalize(basepath, sizeof(basepath), ent->d_name, fname); QCC_JoinPaths(basepath, sizeof(basepath), ent->d_name, fname);
QCC_Canonicalize(tmppath, sizeof(tmppath), basepath, ctx->sourcepath); QCC_JoinPaths(tmppath, sizeof(tmppath), basepath, ctx->sourcepath);
if (stat(tmppath, &statbuf)!=0) if (stat(tmppath, &statbuf)!=0)
continue; continue;
@ -958,7 +958,7 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
*fsize = 0; *fsize = 0;
QCC_Canonicalize(fullname, sizeof(fullname), file->name, ctx->sourcepath); QCC_JoinPaths(fullname, sizeof(fullname), file->name, ctx->sourcepath);
strcpy(file->write.name, file->name); strcpy(file->write.name, file->name);
//WIN32 FIXME: use the utf16 version because microsoft suck and don't allow utf-8 //WIN32 FIXME: use the utf16 version because microsoft suck and don't allow utf-8
@ -996,7 +996,7 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
//delete temp file... //delete temp file...
fclose(f); fclose(f);
QCC_Canonicalize(tempname, sizeof(tempname), file->write.name, ctx->sourcepath); QCC_JoinPaths(tempname, sizeof(tempname), file->write.name, ctx->sourcepath);
f = fopen(tempname, "rb"); f = fopen(tempname, "rb");
if (f) if (f)
{ {
@ -1702,7 +1702,7 @@ void Packager_ParseText(struct pkgctx_s *ctx, char *scripttext)
if (PKG_GetStringToken(ctx, cmd, sizeof(cmd))) if (PKG_GetStringToken(ctx, cmd, sizeof(cmd)))
{ {
QC_strlcat(cmd, "/", sizeof(cmd)); QC_strlcat(cmd, "/", sizeof(cmd));
QCC_Canonicalize(ctx->sourcepath, sizeof(ctx->sourcepath), cmd, old); QCC_JoinPaths(ctx->sourcepath, sizeof(ctx->sourcepath), cmd, old);
} }
} }
else if (!strcmp(cmd, "rule")) else if (!strcmp(cmd, "rule"))

View file

@ -218,56 +218,33 @@ pbool QCC_PR_UnInclude(void)
return true; return true;
} }
void QCC_Canonicalize(char *fullname, size_t fullnamesize, const char *newfile, const char *base) //expresses a relative path relative to an existing FILEname. any directories in base must be / terminated properly.
void QCC_JoinPaths(char *fullname, size_t fullnamesize, const char *newfile, const char *base)
{ {
int doubledots; char *end;
char *end = fullname;
doubledots = 0; if (*newfile == '/' || *newfile == '\\')
{ //its an absolute path...
/*count how far up we need to go*/ QC_strlcpy(fullname, newfile, fullnamesize);
while(1) return;
{
if (!strncmp(newfile, "./", 2) || !strncmp(newfile, ".\\", 2))
newfile+=2;
else if(!strncmp(newfile, "../", 3) || !strncmp(newfile, "..\\", 3))
{
newfile+=3;
doubledots++;
} }
else QC_strlcpy(fullname, base, fullnamesize);
break;
}
//FIXME: length validation!
if (base)
strcpy(fullname, base);
else
*fullname = 0;
end = fullname+strlen(fullname); end = fullname+strlen(fullname);
while (end > fullname) while (end > fullname)
{ {
end--; end--;
/*stop at the slash, unless we're meant to go further*/
if (*end == '/' || *end == '\\') if (*end == '/' || *end == '\\')
{
if (!doubledots)
{ {
end++; end++;
break; break;
} }
doubledots--;
}
} }
QC_strlcpy(end, newfile, fullnamesize - (end-fullname));
while (doubledots-- > 0) //FIXME: do we want to convert /segment/../ into just / ?
{ //fteqw might insist on it for its filesystem sandboxing.
strcpy(end, "../"); //but it breaks symlink weirdness (itself a possible security hole).
end += 3; //should probably be a separate function.
}
strcpy(end, newfile);
} }
extern char qccmsourcedir[]; extern char qccmsourcedir[];
@ -291,7 +268,7 @@ void QCC_FindBestInclude(char *newfile, char *currentfile, pbool verbose)
currentfile = qccincludedir[includepath-1]; currentfile = qccincludedir[includepath-1];
} }
QCC_Canonicalize(fullname, sizeof(fullname), newfile, currentfile); QCC_JoinPaths(fullname, sizeof(fullname), newfile, currentfile);
{ {
extern progfuncs_t *qccprogfuncs; extern progfuncs_t *qccprogfuncs;
@ -954,7 +931,7 @@ static pbool QCC_PR_Precompiler(void)
QCC_ImportProgs(pr_token); QCC_ImportProgs(pr_token);
if (!*destfile && !destfile_explicit) if (!*destfile && !destfile_explicit)
{ {
QCC_Canonicalize(destfile, sizeof(destfile), pr_token, compilingfile); QCC_JoinPaths(destfile, sizeof(destfile), pr_token, compilingfile);
externs->Printf("Outputfile: %s\n", destfile); externs->Printf("Outputfile: %s\n", destfile);
} }
@ -1079,7 +1056,7 @@ static pbool QCC_PR_Precompiler(void)
QCC_PR_SimpleGetString(); QCC_PR_SimpleGetString();
if (!destfile_explicit) if (!destfile_explicit)
{ {
QCC_Canonicalize(destfile, sizeof(destfile), pr_token, compilingfile); QCC_JoinPaths(destfile, sizeof(destfile), pr_token, compilingfile);
externs->Printf("Outputfile: %s\n", pr_token); externs->Printf("Outputfile: %s\n", pr_token);
} }
@ -1213,7 +1190,7 @@ static pbool QCC_PR_Precompiler(void)
QC_strlcat(qcc_token, "/", sizeof(qcc_token)); QC_strlcat(qcc_token, "/", sizeof(qcc_token));
} }
QCC_Canonicalize(newinc, sizeof(newinc), qcc_token, compilingfile); QCC_JoinPaths(newinc, sizeof(newinc), qcc_token, compilingfile);
QCC_PR_AddIncludePath(newinc); QCC_PR_AddIncludePath(newinc);
} }
else if (!QC_strcasecmp(qcc_token, "noref")) else if (!QC_strcasecmp(qcc_token, "noref"))
@ -1332,7 +1309,7 @@ static pbool QCC_PR_Precompiler(void)
QCC_COM_Parse(msg); QCC_COM_Parse(msg);
if (!destfile_explicit) //if output file is named on the commandline, don't change it mid-compile if (!destfile_explicit) //if output file is named on the commandline, don't change it mid-compile
QCC_Canonicalize(destfile, sizeof(destfile), qcc_token, compilingfile); QCC_JoinPaths(destfile, sizeof(destfile), qcc_token, compilingfile);
if (strcmp(destfile, olddest)) if (strcmp(destfile, olddest))
externs->Printf("Outputfile: %s\n", destfile); externs->Printf("Outputfile: %s\n", destfile);