config: clarify memory ownership in `git_config_pathname()`
The out parameter of `git_config_pathname()` is a `const char **` even though we transfer ownership of memory to the caller. This is quite misleading and has led to many memory leaks all over the place. Adapt the parameter to instead be `char **`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
May 27, 2024 at 13:46 UTC
6073b3b5c37716c50244d635e7c358f41f43e286
18 files changed
+44
-39
builtin/blame.c
+1
-1
@@ -718,7 +718,7 @@ static int git_blame_config(const char *var, const char *value,
718
return 0;
719
}
720
if (!strcmp(var, "blame.ignorerevsfile")) {
721
- const char *str;
721
+ char *str;
722
int ret;
723
724
ret = git_config_pathname(&str, var, value);
builtin/commit.c
+1
-1
@@ -107,7 +107,7 @@ static enum {
107
} commit_style;
108
109
static const char *logfile, *force_author;
110
-static const char *template_file;
110
+static char *template_file;
111
/*
112
* The _message variables are commit names from which to take
113
* the commit message and/or authorship.
builtin/config.c
+1
-1
@@ -277,7 +277,7 @@ static int format_config(struct strbuf *buf, const char *key_,
277
else
278
strbuf_addstr(buf, v ? "true" : "false");
279
} else if (type == TYPE_PATH) {
280
- const char *v;
280
+ char *v;
281
if (git_config_pathname(&v, key_, value_) < 0)
282
return -1;
283
strbuf_addstr(buf, v);
builtin/log.c
+1
-1
@@ -957,7 +957,7 @@ static int do_signoff;
957
static enum auto_base_setting auto_base;
958
static char *from;
959
static const char *signature = git_version_string;
960
-static const char *signature_file;
960
+static char *signature_file;
961
static enum cover_setting config_cover_letter;
962
static const char *config_output_directory;
963
static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
builtin/receive-pack.c
+2
-2
@@ -168,13 +168,13 @@ static int receive_pack_config(const char *var, const char *value,
168
}
169
170
if (strcmp(var, "receive.fsck.skiplist") == 0) {
171
- const char *path;
171
+ char *path;
172
173
if (git_config_pathname(&path, var, value))
174
return 1;
175
strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
176
fsck_msg_types.len ? ',' : '=', path);
177
- free((char *)path);
177
+ free(path);
178
return 0;
179
}
180
config.c
+5
-5
@@ -1346,7 +1346,7 @@ int git_config_string(const char **dest, const char *var, const char *value)
1346
return 0;
1347
}
1348
1349
-int git_config_pathname(const char **dest, const char *var, const char *value)
1349
+int git_config_pathname(char **dest, const char *var, const char *value)
1350
{
1351
if (!value)
1352
return config_error_nonbool(var);
@@ -1597,7 +1597,7 @@ static int git_default_core_config(const char *var, const char *value,
1597
return git_config_string(&askpass_program, var, value);
1598
1599
if (!strcmp(var, "core.excludesfile")) {
1600
- free((char *)excludes_file);
1600
+ free(excludes_file);
1601
return git_config_pathname(&excludes_file, var, value);
1602
}
1603
@@ -2494,7 +2494,7 @@ int git_configset_get_maybe_bool(struct config_set *set, const char *key, int *d
2494
return 1;
2495
}
2496
2497
-int git_configset_get_pathname(struct config_set *set, const char *key, const char **dest)
2497
+int git_configset_get_pathname(struct config_set *set, const char *key, char **dest)
2498
{
2499
const char *value;
2500
if (!git_configset_get_value(set, key, &value, NULL))
@@ -2639,7 +2639,7 @@ int repo_config_get_maybe_bool(struct repository *repo,
2639
}
2640
2641
int repo_config_get_pathname(struct repository *repo,
2642
- const char *key, const char **dest)
2642
+ const char *key, char **dest)
2643
{
2644
int ret;
2645
git_config_check_init(repo);
@@ -2738,7 +2738,7 @@ int git_config_get_maybe_bool(const char *key, int *dest)
2738
return repo_config_get_maybe_bool(the_repository, key, dest);
2739
}
2740
2741
-int git_config_get_pathname(const char *key, const char **dest)
2741
+int git_config_get_pathname(const char *key, char **dest)
2742
{
2743
return repo_config_get_pathname(the_repository, key, dest);
2744
}
config.h
+4
-4
@@ -286,7 +286,7 @@ int git_config_string(const char **, const char *, const char *);
286
* Similar to `git_config_string`, but expands `~` or `~user` into the
287
* user's home directory when found at the beginning of the path.
288
*/
289
-int git_config_pathname(const char **, const char *, const char *);
289
+int git_config_pathname(char **, const char *, const char *);
290
291
int git_config_expiry_date(timestamp_t *, const char *, const char *);
292
int git_config_color(char *, const char *, const char *);
@@ -541,7 +541,7 @@ int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned lon
541
int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
542
int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
543
int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
544
-int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
544
+int git_configset_get_pathname(struct config_set *cs, const char *key, char **dest);
545
546
/* Functions for reading a repository's config */
547
struct repository;
@@ -577,7 +577,7 @@ int repo_config_get_bool_or_int(struct repository *repo,
577
int repo_config_get_maybe_bool(struct repository *repo,
578
const char *key, int *dest);
579
int repo_config_get_pathname(struct repository *repo,
580
- const char *key, const char **dest);
580
+ const char *key, char **dest);
581
582
/*
583
* Functions for reading protected config. By definition, protected
@@ -687,7 +687,7 @@ int git_config_get_maybe_bool(const char *key, int *dest);
687
* Similar to `git_config_get_string`, but expands `~` or `~user` into
688
* the user's home directory when found at the beginning of the path.
689
*/
690
-int git_config_get_pathname(const char *key, const char **dest);
690
+int git_config_get_pathname(const char *key, char **dest);
691
692
int git_config_get_index_threads(int *dest);
693
int git_config_get_split_index(void);
diff.c
+1
-1
@@ -58,7 +58,7 @@ static int diff_context_default = 3;
58
static int diff_interhunk_context_default;
59
static const char *diff_word_regex_cfg;
60
static const char *external_diff_cmd_cfg;
61
-static const char *diff_order_file_cfg;
61
+static char *diff_order_file_cfg;
62
int diff_auto_refresh_index = 1;
63
static int diff_mnemonic_prefix;
64
static int diff_no_prefix;
environment.c
+3
-3
@@ -46,8 +46,8 @@ const char *git_commit_encoding;
46
const char *git_log_output_encoding;
47
char *apply_default_whitespace;
48
char *apply_default_ignorewhitespace;
49
-const char *git_attributes_file;
50
-const char *git_hooks_path;
49
+char *git_attributes_file;
50
+char *git_hooks_path;
51
int zlib_compression_level = Z_BEST_SPEED;
52
int pack_compression_level = Z_DEFAULT_COMPRESSION;
53
int fsync_object_files = -1;
@@ -60,7 +60,7 @@ size_t delta_base_cache_limit = 96 * 1024 * 1024;
60
unsigned long big_file_threshold = 512 * 1024 * 1024;
61
const char *editor_program;
62
const char *askpass_program;
63
-const char *excludes_file;
63
+char *excludes_file;
64
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
65
enum eol core_eol = EOL_UNSET;
66
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
environment.h
+3
-3
@@ -131,8 +131,8 @@ extern int warn_ambiguous_refs;
131
extern int warn_on_object_refname_ambiguity;
132
extern char *apply_default_whitespace;
133
extern char *apply_default_ignorewhitespace;
134
-extern const char *git_attributes_file;
135
-extern const char *git_hooks_path;
134
+extern char *git_attributes_file;
135
+extern char *git_hooks_path;
136
extern int zlib_compression_level;
137
extern int pack_compression_level;
138
extern size_t packed_git_window_size;
@@ -229,7 +229,7 @@ extern const char *git_log_output_encoding;
229
230
extern const char *editor_program;
231
extern const char *askpass_program;
232
-extern const char *excludes_file;
232
+extern char *excludes_file;
233
234
/*
235
* Should we print an ellipsis after an abbreviated SHA-1 value
fetch-pack.c
+2
-2
@@ -1865,13 +1865,13 @@ static int fetch_pack_config_cb(const char *var, const char *value,
1865
const char *msg_id;
1866
1867
if (strcmp(var, "fetch.fsck.skiplist") == 0) {
1868
- const char *path;
1868
+ char *path ;
1869
1870
if (git_config_pathname(&path, var, value))
1871
return 1;
1872
strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
1873
fsck_msg_types.len ? ',' : '=', path);
1874
- free((char *)path);
1874
+ free(path);
1875
return 0;
1876
}
1877
fsck.c
+2
-2
@@ -1330,13 +1330,13 @@ int git_fsck_config(const char *var, const char *value,
1330
const char *msg_id;
1331
1332
if (strcmp(var, "fsck.skiplist") == 0) {
1333
- const char *path;
1333
+ char *path;
1334
struct strbuf sb = STRBUF_INIT;
1335
1336
if (git_config_pathname(&path, var, value))
1337
return 1;
1338
strbuf_addf(&sb, "skiplist=%s", path);
1339
- free((char *)path);
1339
+ free(path);
1340
fsck_set_msg_types(options, sb.buf);
1341
strbuf_release(&sb);
1342
return 0;
fsmonitor-settings.c
+4
-1
@@ -103,6 +103,7 @@ static struct fsmonitor_settings *alloc_settings(void)
103
static void lookup_fsmonitor_settings(struct repository *r)
104
{
105
const char *const_str;
106
+ char *to_free = NULL;
107
int bool_value;
108
109
if (r->settings.fsmonitor)
@@ -129,8 +130,9 @@ static void lookup_fsmonitor_settings(struct repository *r)
130
break;
131
132
case -1: /* config value set to an arbitrary string */
132
- if (repo_config_get_pathname(r, "core.fsmonitor", &const_str))
133
+ if (repo_config_get_pathname(r, "core.fsmonitor", &to_free))
134
return; /* should not happen */
135
+ const_str = to_free;
136
break;
137
138
default: /* should not happen */
@@ -141,6 +143,7 @@ static void lookup_fsmonitor_settings(struct repository *r)
143
fsm_settings__set_hook(r, const_str);
144
else
145
fsm_settings__set_disabled(r);
146
+ free(to_free);
147
}
148
149
enum fsmonitor_mode fsm_settings__get_mode(struct repository *r)
gpg-interface.c
+3
-1
@@ -27,7 +27,9 @@ static void gpg_interface_lazy_init(void)
27
}
28
29
static char *configured_signing_key;
30
-static const char *ssh_default_key_command, *ssh_allowed_signers, *ssh_revocation_file;
30
+static const char *ssh_default_key_command;
31
+static char *ssh_allowed_signers;
32
+static char *ssh_revocation_file;
33
static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
34
35
struct gpg_format {
http.c
+6
-6
@@ -64,7 +64,7 @@ static char *ssl_key_type;
64
static char *ssl_capath;
65
static char *curl_no_proxy;
66
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
67
-static const char *ssl_pinnedkey;
67
+static char *ssl_pinnedkey;
68
#endif
69
static char *ssl_cainfo;
70
static long curl_low_speed_limit = -1;
@@ -108,7 +108,7 @@ static struct {
108
109
static struct credential proxy_auth = CREDENTIAL_INIT;
110
static const char *curl_proxyuserpwd;
111
-static const char *curl_cookie_file;
111
+static char *curl_cookie_file;
112
static int curl_save_cookies;
113
struct credential http_auth = CREDENTIAL_INIT;
114
static int http_proactive_auth;
@@ -381,17 +381,17 @@ static int http_options(const char *var, const char *value,
381
if (!strcmp("http.sslversion", var))
382
return git_config_string(&ssl_version, var, value);
383
if (!strcmp("http.sslcert", var))
384
- return git_config_pathname((const char **)&ssl_cert, var, value);
384
+ return git_config_pathname(&ssl_cert, var, value);
385
if (!strcmp("http.sslcerttype", var))
386
return git_config_string((const char **)&ssl_cert_type, var, value);
387
if (!strcmp("http.sslkey", var))
388
- return git_config_pathname((const char **)&ssl_key, var, value);
388
+ return git_config_pathname(&ssl_key, var, value);
389
if (!strcmp("http.sslkeytype", var))
390
return git_config_string((const char **)&ssl_key_type, var, value);
391
if (!strcmp("http.sslcapath", var))
392
- return git_config_pathname((const char **)&ssl_capath, var, value);
392
+ return git_config_pathname(&ssl_capath, var, value);
393
if (!strcmp("http.sslcainfo", var))
394
- return git_config_pathname((const char **)&ssl_cainfo, var, value);
394
+ return git_config_pathname(&ssl_cainfo, var, value);
395
if (!strcmp("http.sslcertpasswordprotected", var)) {
396
ssl_cert_password_required = git_config_bool(var, value);
397
return 0;
mailmap.c
+1
-1
@@ -6,7 +6,7 @@
6
#include "object-store-ll.h"
7
#include "setup.h"
8
9
-const char *git_mailmap_file;
9
+char *git_mailmap_file;
10
const char *git_mailmap_blob;
11
12
struct mailmap_info {
mailmap.h
+1
-1
@@ -3,7 +3,7 @@
3
4
struct string_list;
5
6
-extern const char *git_mailmap_file;
6
+extern char *git_mailmap_file;
7
extern const char *git_mailmap_blob;
8
9
int read_mailmap(struct string_list *map);
setup.c
+3
-3
@@ -1177,13 +1177,13 @@ static int safe_directory_cb(const char *key, const char *value,
1177
} else if (!strcmp(value, "*")) {
1178
data->is_safe = 1;
1179
} else {
1180
- const char *interpolated = NULL;
1180
+ char *interpolated = NULL;
1181
1182
if (!git_config_pathname(&interpolated, key, value) &&
1183
!fspathcmp(data->path, interpolated ? interpolated : value))
1184
data->is_safe = 1;
1185
1186
- free((char *)interpolated);
1186
+ free(interpolated);
1187
}
1188
1189
return 0;
@@ -1822,7 +1822,7 @@ static int template_dir_cb(const char *key, const char *value,
1822
char *path = NULL;
1823
1824
FREE_AND_NULL(data->path);
1825
- if (!git_config_pathname((const char **)&path, key, value))
1825
+ if (!git_config_pathname(&path, key, value))
1826
data->path = path ? path : xstrdup(value);
1827
}
1828