fa416c484061b1e44519962435588916dc14a1f7 markd Wed Dec 9 22:04:07 2020 -0800 added isSafeRelativePath and removed way too low-level verbose logging diff --git src/lib/filePath.c src/lib/filePath.c index 7da8293..30a0d0d 100644 --- src/lib/filePath.c +++ src/lib/filePath.c @@ -109,59 +109,57 @@ memcpy(result, baseDir, baseSize); result[baseSize] = '/'; strcpy(result + baseSize + 1, rel); } else result = cloneString(rel); return result; } char *mustExpandRelativePath(char *dir, char* relPath) /* Given a dir and relative path, expand path. * Handy for processing symlinks. errAbort if expand fails. * Result should be freeMem'd.*/ { char *path = expandRelativePath(dir, relPath); -verbose(3, "dir=%s\nrelPath=%s\npath=%s\n", dir, relPath, path); if (!path) errAbort("Too many .. in path %s to make relative to submitDir %s\n", relPath, dir); return path; } char *pathRelativeToFile(char *baseFile, char *relPath) /* Given a base file name and a path relative to that, return * relative path interpreted as if it were seen from the * same directory holding the baseFile. * An example of using this would be in processing include * files. In this case the baseFile would be the current * source file, and the relPath would be from the include * statement. The returned result could then be used to * open the include file. */ { char dir[PATH_LEN]; splitPath(baseFile, dir, NULL, NULL); int dirLen = strlen(dir); if (dirLen > 0 && dir[dirLen-1] == '/') dir[dirLen-1] = 0; return expandRelativePath(dir, relPath); } char *mustPathRelativeToFile(char *baseFile, char *relPath) /* Make Path Relative To File or Abort. */ { char *path = pathRelativeToFile(baseFile, relPath); -verbose(3, "baseFile=%s\nrelPath=%s\npath=%s\n", baseFile, relPath, path); if (!path) errAbort("Too many .. in symlink path %s to make relative to %s\n", relPath, baseFile); return path; } char *makeRelativePath(char *from, char *to) /* Calculate a relative path from one absolute directory/file to another. * Assumptions: both from and to are canonicalized absolute paths beginning * at "/" or "//". Filenames are okay, but all directory names must end with * a "/" to distinguish them from files. * e.g., /test/dir/ is a directory, but /test/dir is a file. */ { int i, j, toCount, fromCount; char fromDir[PATH_LEN]; @@ -201,15 +199,39 @@ for (j=i; j < fromCount-1; j++) { safecat(relPath, sizeof relPath, "../"); } for (j=i; j < toCount-1; j++) { safecat(relPath, sizeof relPath, toDirList[j]); safecat(relPath, sizeof relPath, "/"); } safecat(relPath, sizeof relPath, toFile); safecat(relPath, sizeof relPath, toExt); return cloneString(relPath); } + +boolean isSafeRelativePath(char *path) +/* check that path is relative and contains no ".." elements */ +{ +if (startsWith("/", path)) + return FALSE; +char tmpPath[PATH_LEN]; +safecpy(tmpPath, sizeof(tmpPath), path); + +char *p = tmpPath; +while (TRUE) + { + char *end = strchr(p, '/'); + if (end != NULL) + *end = '\0'; + if (sameString(p, "..")) + return FALSE; + if (end == NULL) + break; + else + p = end++; + } +return TRUE; +}