From 062daeb81d63a29ee7ac5439a56bf906707317f8 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 7 Aug 2026 15:55:09 +0200 Subject: [PATCH] setup: add 'allow_dot' arg to path_allowlist_apply() A previous commit created path_allowlist_apply() with the goal of later reusing that function. But when it will be reused in a following commit this function will need to reject non-absolute paths including those with a single dot that are currently accepted. To prepare for reusing path_allowlist_apply(), let's add a `bool allow_dot` argument to it, and let's export this function. While at it let's document it properly in "setup.h". Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- setup.c | 9 +++++---- setup.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/setup.c b/setup.c index 734875c146..3fc906939d 100644 --- a/setup.c +++ b/setup.c @@ -1329,8 +1329,9 @@ static int canonicalize_ceiling_entry(struct string_list_item *item, } } -static void path_allowlist_apply(const char *key, const char *value, - const char *target_path, int *is_match) +void path_allowlist_apply(const char *key, const char *value, + const char *target_path, int *is_match, + bool allow_dot) { char *allowed = NULL; char *normalized = NULL; @@ -1356,7 +1357,7 @@ static void path_allowlist_apply(const char *key, const char *value, * OK", which is slightly tighter than "*" that allows * discovery. */ - if (!is_absolute_path(allowed) && strcmp(allowed, ".")) { + if (!is_absolute_path(allowed) && (!allow_dot || strcmp(allowed, "."))) { warning(_("%s '%s' not absolute"), key, allowed); goto end; } @@ -1400,7 +1401,7 @@ static int safe_directory_cb(const char *key, const char *value, if (strcmp(key, "safe.directory")) return 0; - path_allowlist_apply(key, value, data->path, &data->is_safe); + path_allowlist_apply(key, value, data->path, &data->is_safe, true); return 0; } diff --git a/setup.h b/setup.h index 705d1d6ff7..3bb9688fb7 100644 --- a/setup.h +++ b/setup.h @@ -299,4 +299,32 @@ struct startup_info { extern struct startup_info *startup_info; extern const char *tmp_original_cwd; +/* + * Apply the path allowlist in 'value' against 'target_path' setting + * '*is_match' accordingly. + * + * `value` is the value of a multi-valued config variable named `key` + * that holds an allowlist of paths. `target_path` is the (normalized) + * path being tested. `*is_match` is updated in place: + * + * - an empty value resets it to 0 (so a later, more specific config + * scope can clear entries from a broader one), + * - "*" sets it to 1 (allow everything), + * - "" sets it to 1 if equals `target_path`, + * - "" + "/" + "*" sets it to 1 if is a leading + * directory of `target_path`, + * - any other (unmatching) value leaves `*is_match` unchanged. + * + * Non-absolute values are rejected with a warning, except "." when + * `allow_dot` is set (used by 'safe.directory' to mean "the top level + * of the current repository"). + * + * Callers are expected to invoke this once per config value, + * typically from a protected-config callback, so that untrusted + * repository config cannot influence the decision. + */ +void path_allowlist_apply(const char *key, const char *value, + const char *target_path, int *is_match, + bool allow_dot); + #endif /* SETUP_H */