@@ -1005,6 +1005,9 @@ static int submodule_has_commits(struct repository *r,
10051005 .super_oid = super_oid
10061006 };
10071007
1008+ if (validate_submodule_path (path ) < 0 )
1009+ exit (128 );
1010+
10081011 oid_array_for_each_unique (commits , check_has_commit , & has_commit );
10091012
10101013 if (has_commit .result ) {
@@ -1127,6 +1130,9 @@ static int push_submodule(const char *path,
11271130 const struct string_list * push_options ,
11281131 int dry_run )
11291132{
1133+ if (validate_submodule_path (path ) < 0 )
1134+ exit (128 );
1135+
11301136 if (for_each_remote_ref_submodule (path , has_remote , NULL ) > 0 ) {
11311137 struct child_process cp = CHILD_PROCESS_INIT ;
11321138 strvec_push (& cp .args , "push" );
@@ -1176,6 +1182,9 @@ static void submodule_push_check(const char *path, const char *head,
11761182 struct child_process cp = CHILD_PROCESS_INIT ;
11771183 int i ;
11781184
1185+ if (validate_submodule_path (path ) < 0 )
1186+ exit (128 );
1187+
11791188 strvec_push (& cp .args , "submodule--helper" );
11801189 strvec_push (& cp .args , "push-check" );
11811190 strvec_push (& cp .args , head );
@@ -1507,6 +1516,9 @@ static struct fetch_task *fetch_task_create(struct submodule_parallel_fetch *spf
15071516 struct fetch_task * task = xmalloc (sizeof (* task ));
15081517 memset (task , 0 , sizeof (* task ));
15091518
1519+ if (validate_submodule_path (path ) < 0 )
1520+ exit (128 );
1521+
15101522 task -> sub = submodule_from_path (spf -> r , treeish_name , path );
15111523
15121524 if (!task -> sub ) {
@@ -1879,6 +1891,9 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
18791891 const char * git_dir ;
18801892 int ignore_cp_exit_code = 0 ;
18811893
1894+ if (validate_submodule_path (path ) < 0 )
1895+ exit (128 );
1896+
18821897 strbuf_addf (& buf , "%s/.git" , path );
18831898 git_dir = read_gitfile (buf .buf );
18841899 if (!git_dir )
@@ -1955,6 +1970,9 @@ int submodule_uses_gitfile(const char *path)
19551970 struct strbuf buf = STRBUF_INIT ;
19561971 const char * git_dir ;
19571972
1973+ if (validate_submodule_path (path ) < 0 )
1974+ exit (128 );
1975+
19581976 strbuf_addf (& buf , "%s/.git" , path );
19591977 git_dir = read_gitfile (buf .buf );
19601978 if (!git_dir ) {
@@ -1994,6 +2012,9 @@ int bad_to_remove_submodule(const char *path, unsigned flags)
19942012 struct strbuf buf = STRBUF_INIT ;
19952013 int ret = 0 ;
19962014
2015+ if (validate_submodule_path (path ) < 0 )
2016+ exit (128 );
2017+
19972018 if (!file_exists (path ) || is_empty_dir (path ))
19982019 return 0 ;
19992020
@@ -2044,6 +2065,9 @@ void submodule_unset_core_worktree(const struct submodule *sub)
20442065{
20452066 struct strbuf config_path = STRBUF_INIT ;
20462067
2068+ if (validate_submodule_path (sub -> path ) < 0 )
2069+ exit (128 );
2070+
20472071 submodule_name_to_gitdir (& config_path , the_repository , sub -> name );
20482072 strbuf_addstr (& config_path , "/config" );
20492073
@@ -2066,6 +2090,9 @@ static int submodule_has_dirty_index(const struct submodule *sub)
20662090{
20672091 struct child_process cp = CHILD_PROCESS_INIT ;
20682092
2093+ if (validate_submodule_path (sub -> path ) < 0 )
2094+ exit (128 );
2095+
20692096 prepare_submodule_repo_env (& cp .env );
20702097
20712098 cp .git_cmd = 1 ;
@@ -2083,6 +2110,10 @@ static int submodule_has_dirty_index(const struct submodule *sub)
20832110static void submodule_reset_index (const char * path )
20842111{
20852112 struct child_process cp = CHILD_PROCESS_INIT ;
2113+
2114+ if (validate_submodule_path (path ) < 0 )
2115+ exit (128 );
2116+
20862117 prepare_submodule_repo_env (& cp .env );
20872118
20882119 cp .git_cmd = 1 ;
@@ -2287,6 +2318,34 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
22872318 return 0 ;
22882319}
22892320
2321+ int validate_submodule_path (const char * path )
2322+ {
2323+ char * p = xstrdup (path );
2324+ struct stat st ;
2325+ int i , ret = 0 ;
2326+ char sep ;
2327+
2328+ for (i = 0 ; !ret && p [i ]; i ++ ) {
2329+ if (!is_dir_sep (p [i ]))
2330+ continue ;
2331+
2332+ sep = p [i ];
2333+ p [i ] = '\0' ;
2334+ /* allow missing components, but no symlinks */
2335+ ret = lstat (p , & st ) || !S_ISLNK (st .st_mode ) ? 0 : -1 ;
2336+ p [i ] = sep ;
2337+ if (ret )
2338+ error (_ ("expected '%.*s' in submodule path '%s' not to "
2339+ "be a symbolic link" ), i , p , p );
2340+ }
2341+ if (!lstat (p , & st ) && S_ISLNK (st .st_mode ))
2342+ ret = error (_ ("expected submodule path '%s' not to be a "
2343+ "symbolic link" ), p );
2344+ free (p );
2345+ return ret ;
2346+ }
2347+
2348+
22902349/*
22912350 * Embeds a single submodules git directory into the superprojects git dir,
22922351 * non recursively.
@@ -2297,6 +2356,9 @@ static void relocate_single_git_dir_into_superproject(const char *path)
22972356 struct strbuf new_gitdir = STRBUF_INIT ;
22982357 const struct submodule * sub ;
22992358
2359+ if (validate_submodule_path (path ) < 0 )
2360+ exit (128 );
2361+
23002362 if (submodule_uses_worktrees (path ))
23012363 die (_ ("relocate_gitdir for submodule '%s' with "
23022364 "more than one worktree not supported" ), path );
@@ -2337,6 +2399,9 @@ static void absorb_git_dir_into_superproject_recurse(const char *path)
23372399
23382400 struct child_process cp = CHILD_PROCESS_INIT ;
23392401
2402+ if (validate_submodule_path (path ) < 0 )
2403+ exit (128 );
2404+
23402405 cp .dir = path ;
23412406 cp .git_cmd = 1 ;
23422407 cp .no_stdin = 1 ;
@@ -2359,6 +2424,10 @@ void absorb_git_dir_into_superproject(const char *path)
23592424 int err_code ;
23602425 const char * sub_git_dir ;
23612426 struct strbuf gitdir = STRBUF_INIT ;
2427+
2428+ if (validate_submodule_path (path ) < 0 )
2429+ exit (128 );
2430+
23622431 strbuf_addf (& gitdir , "%s/.git" , path );
23632432 sub_git_dir = resolve_gitdir_gently (gitdir .buf , & err_code );
23642433
@@ -2501,6 +2570,9 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
25012570 const char * git_dir ;
25022571 int ret = 0 ;
25032572
2573+ if (validate_submodule_path (submodule ) < 0 )
2574+ exit (128 );
2575+
25042576 strbuf_reset (buf );
25052577 strbuf_addstr (buf , submodule );
25062578 strbuf_complete (buf , '/' );
0 commit comments