diff options
context:
space:
mode:
Diffstat (limited to 'source/ui-summary.c')
-rw-r--r--source/ui-summary.c17
1 file changed, 13 insertions, 4 deletions
diff --git a/source/ui-summary.c b/source/ui-summary.c
index ea8f783..da530e5 100644
--- a/source/ui-summary.c
+++ b/source/ui-summary.c
@@ -71,10 +71,10 @@ static int path_within(const char *base, const char *path)
static char *resolve_about_path(const char *filename, const char *ref, const char *path)
{
char *copy, *base_dir, *full_path;
- char *resolved_base = NULL, *resolved_full = NULL;
+ char *resolved_base = NULL, *resolved_full = NULL, *resolved_repo = NULL;
// dirname is allowed to write into its argument and to return a
- // pointer into it, so base_dir borrows from a copy we keep alive.
+ // pointer into it, so base_dir borrows from a copy freed at the end.
copy = xstrdup(filename);
base_dir = dirname(copy);
if (!strcmp(base_dir, ".") || !strcmp(base_dir, "..")) {
@@ -83,13 +83,21 @@ static char *resolve_about_path(const char *filename, const char *ref, const cha
return NULL;
}
full_path = xstrdup(path);
- } else
+ } else {
full_path = cgit_fmtalloc("%s/%s", base_dir, path);
+ }
+ // A readme in the repository directory, or above it, would open the
+ // repository's own files, its config and hooks among them.
if (!ref) {
resolved_base = realpath(base_dir, NULL);
resolved_full = realpath(full_path, NULL);
- if (!resolved_base || !resolved_full || !path_within(resolved_base, resolved_full)) {
+ resolved_repo = realpath(ctx.repo->path, NULL);
+ if (
+ !resolved_base || !resolved_full || !resolved_repo ||
+ path_within(resolved_base, resolved_repo) ||
+ !path_within(resolved_base, resolved_full)
+ ) {
free(full_path);
full_path = NULL;
}
@@ -98,6 +106,7 @@ static char *resolve_about_path(const char *filename, const char *ref, const cha
free(copy);
free(resolved_base);
free(resolved_full);
+ free(resolved_repo);
return full_path;
}