The changes of e8d0608944 (submodule: require the submodule path to contain directories only, 2024-03-26) as part of "defense in depth" strategy made it impossible to intentionally use symlinks instead of actual submodule directories, which can be desirable when the same big submodule is used by multiple projects. Reintroduce the possibility to do it by adding a new submodule.<name>.validate option which defaults to 1, but can be explicitly set to 0 to disable the submodule path validation. Signed-off-by: Vadim Zeitlin <vadim@xxxxxxxxxxxx> --- Documentation/config/submodule.adoc | 8 ++++++++ submodule.c | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Documentation/config/submodule.adoc b/Documentation/config/submodule.adoc index 0672d99117..92243458c2 100644 --- a/Documentation/config/submodule.adoc +++ b/Documentation/config/submodule.adoc @@ -106,3 +106,11 @@ submodule.alternateErrorStrategy:: `ignore`, `info`, `die`. Default is `die`. Note that if set to `ignore` or `info`, and if there is an error with the computed alternate, the clone proceeds as if no alternate was specified. + +submodule.validate:: + A boolean value which can be set to false to disable validation of + submodule paths and notably checking that they don't contain any symlink + components. This can be useful when working with a trusted repository and + intentionally using symlinks to avoid checking out another copy of the same + submodule which already exists elsewhere on the same machine. + Defaults to true. diff --git a/submodule.c b/submodule.c index f8373a9ea7..01b852c673 100644 --- a/submodule.c +++ b/submodule.c @@ -2299,11 +2299,28 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name) int validate_submodule_path(const char *path) { - char *p = xstrdup(path); + char *key = NULL; + int validate = 1; + + char *p = NULL; struct stat st; int i, ret = 0; char sep; + const struct submodule *submodule; + + submodule = submodule_from_path(the_repository, null_oid(the_hash_algo), path); + if (!submodule) + BUG("could not get submodule information for '%s'", path); + + /* Check if submodule.<name>.validate is set to false to skip the check. */ + key = xstrfmt("submodule.%s.validate", submodule->name); + repo_config_get_bool(the_repository, key, &validate); + free(key); + if (!validate) + return 0; + + p = xstrdup(path); for (i = 0; !ret && p[i]; i++) { if (!is_dir_sep(p[i])) continue; -- 2.47.2