Having ... [core] excludesFile = /some/global/path/.gitignore ... this triggers a leak: $ GIT_EDITOR=: git rebase -i HEAD Successfully rebased and updated detached HEAD. ================================================================= ==...==ERROR: LeakSanitizer: detected memory leaks Direct leak of 60 byte(s) in 1 object(s) allocated from: #0 ... in realloc #1 ... in xrealloc wrapper.c:137 #2 ... in strbuf_grow strbuf.c:112 #3 ... in strbuf_add strbuf.c:311 #4 ... in strbuf_addstr strbuf.h:310 #5 ... in interpolate_path path.c:771 #6 ... in git_config_pathname config.c:1352 #7 ... in git_default_core_config config.c:1588 #8 ... in git_default_config config.c:1791 #9 ... in rebase_config builtin/rebase.c:801 #10 ... in configset_iter config.c:2161 #11 ... in repo_config config.c:2540 #12 ... in git_config config.c:2663 #13 ... in cmd_rebase builtin/rebase.c:1187 #14 ... in run_builtin git.c:469 #15 ... in handle_builtin git.c:724 #16 ... in run_argv git.c:788 #17 ... in cmd_main git.c:923 #18 ... in main common-main.c:62 It happens because we parse twice the configuration: $ GIT_EDITOR=: gdb --ex "break git_config" --ex "run" --args git rebase -i HEAD (gdb) bt #0 git_config () at config.c:2663 #1 ... in cmd_rebase () at builtin/rebase.c:1187 #2 ... in run_builtin () at git.c:469 #3 ... in handle_builtin () at git.c:724 #4 ... in run_argv () at git.c:788 #5 ... in cmd_main () at git.c:923 #6 ... in main () at common-main.c:62 (gdb) c (gdb) bt #0 git_config () at config.c:2663 #1 ... in sequencer_init_config () at sequencer.c:291 #2 ... in get_replay_opts () at builtin/rebase.c:161 #3 ... in do_interactive_rebase () at builtin/rebase.c:271 #4 ... in run_sequencer_rebase () at builtin/rebase.c:339 #5 ... in run_specific_rebase () at builtin/rebase.c:705 #6 ... in cmd_rebase () at builtin/rebase.c:1830 #7 ... in run_builtin () at git.c:469 #8 ... in handle_builtin () at git.c:724 #9 ... in run_argv () at git.c:788 #10 ... in cmd_main () at git.c:923 #11 ... in main () at common-main.c:62 We call twice to git_config(): first to get the main git-branch(1) options, and second to get the ones related to the sequencer. Due to how git_config() works the global configuration is parsed twice, therefore if core.excludesFile is set, it will be allocated twice. A free() before the git_config_pathname() can be a simpler fix, but I think this series offers a better approach, perhaps applicable to other potential similar leaks. Rubén Justo (4): path.c: introduce strbuf_interpolate_path config.c: introduce git_config_strbuf_pathname environment.c: convert excludes_file to struct strbuf t7300: mark as leak-free config.c | 12 +++++++++++- config.h | 2 ++ dir.c | 13 +++++++++---- environment.c | 2 +- environment.h | 2 +- path.c | 20 ++++++++++++++------ path.h | 1 + t/t7300-clean.sh | 1 + 8 files changed, 40 insertions(+), 13 deletions(-) -- 2.44.0.697.g9b33b46f29