]> git.ipfire.org Git - thirdparty/git.git/commitdiff
worktree: do not pass strbuf by value
authorDeveshi Dwivedi <deveshigurgaon@gmail.com>
Wed, 11 Mar 2026 17:33:35 +0000 (17:33 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 Mar 2026 18:08:53 +0000 (11:08 -0700)
write_worktree_linking_files() takes two struct strbuf parameters by
value, even though it only reads path strings from them.

Passing a strbuf by value is misleading and dangerous. The structure
carries a pointer to its underlying character array; caller and callee
end up sharing that storage.  If the callee ever causes the strbuf to
be reallocated, the caller's copy becomes a dangling pointer, which
results in a double-free when the caller does strbuf_release().

The function only needs the string values, not the strbuf machinery.
Switch it to take const char * and update all callers to pass .buf.

Signed-off-by: Deveshi Dwivedi <deveshigurgaon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/worktree.c
worktree.c
worktree.h

index bc2d0d645ba945339281a1381d837f03889a70fe..4035b1cb06cba77607df96475a7b0cc6aa32f20b 100644 (file)
@@ -539,7 +539,7 @@ static int add_worktree(const char *path, const char *refname,
 
        strbuf_reset(&sb);
        strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
-       write_worktree_linking_files(sb_git, sb, opts->relative_paths);
+       write_worktree_linking_files(sb_git.buf, sb.buf, opts->relative_paths);
        strbuf_reset(&sb);
        strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
        write_file(sb.buf, "../..");
index 6e2f0f78283dbf4ed969d90aa14b539f35857673..7eba12c6edc248af236dd62004a8901d9ca82a96 100644 (file)
@@ -445,7 +445,7 @@ void update_worktree_location(struct worktree *wt, const char *path_,
        strbuf_realpath(&path, path_, 1);
        strbuf_addf(&dotgit, "%s/.git", path.buf);
        if (fspathcmp(wt->path, path.buf)) {
-               write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+               write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
 
                free(wt->path);
                wt->path = strbuf_detach(&path, NULL);
@@ -684,7 +684,7 @@ static void repair_gitfile(struct worktree *wt,
 
        if (repair) {
                fn(0, wt->path, repair, cb_data);
-               write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+               write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
        }
 
 done:
@@ -742,7 +742,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
        if (!file_exists(dotgit.buf))
                goto done;
 
-       write_worktree_linking_files(dotgit, gitdir, is_relative_path);
+       write_worktree_linking_files(dotgit.buf, gitdir.buf, is_relative_path);
 done:
        strbuf_release(&gitdir);
        strbuf_release(&dotgit);
@@ -913,7 +913,7 @@ void repair_worktree_at_path(const char *path,
 
        if (repair) {
                fn(0, gitdir.buf, repair, cb_data);
-               write_worktree_linking_files(dotgit, gitdir, use_relative_paths);
+               write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths);
        }
 done:
        free(dotgit_contents);
@@ -1087,17 +1087,17 @@ cleanup:
        return res;
 }
 
-void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
+void write_worktree_linking_files(const char *dotgit, const char *gitdir,
                                  int use_relative_paths)
 {
        struct strbuf path = STRBUF_INIT;
        struct strbuf repo = STRBUF_INIT;
        struct strbuf tmp = STRBUF_INIT;
 
-       strbuf_addbuf(&path, &dotgit);
+       strbuf_addstr(&path, dotgit);
        strbuf_strip_suffix(&path, "/.git");
        strbuf_realpath(&path, path.buf, 1);
-       strbuf_addbuf(&repo, &gitdir);
+       strbuf_addstr(&repo, gitdir);
        strbuf_strip_suffix(&repo, "/gitdir");
        strbuf_realpath(&repo, repo.buf, 1);
 
@@ -1110,11 +1110,11 @@ void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
        }
 
        if (use_relative_paths) {
-               write_file(gitdir.buf, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
-               write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));
+               write_file(gitdir, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
+               write_file(dotgit, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));
        } else {
-               write_file(gitdir.buf, "%s/.git", path.buf);
-               write_file(dotgit.buf, "gitdir: %s", repo.buf);
+               write_file(gitdir, "%s/.git", path.buf);
+               write_file(dotgit, "gitdir: %s", repo.buf);
        }
 
        strbuf_release(&path);
index 06efe26b835a81adc9e78b74544c1a7f93884414..f4e46be385afd4d7bd1b178183f4922dacf75652 100644 (file)
@@ -240,7 +240,7 @@ int init_worktree_config(struct repository *r);
  *  dotgit: "/path/to/foo/.git"
  *  gitdir: "/path/to/repo/worktrees/foo/gitdir"
  */
-void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
+void write_worktree_linking_files(const char *dotgit, const char *gitdir,
                                  int use_relative_paths);
 
 #endif