config: clarify memory ownership in `git_config_string()`

The out parameter of `git_config_string()` 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 1b261c20ed28ad26ddbcd3dff94a248ac6866ac8
30 files changed +96 -92
alias.c
+1 -1
@@ -22,7 +22,7 @@ static int config_alias_cb(const char *key, const char *value,
22
23 if (data->alias) {
24 if (!strcasecmp(p, data->alias))
25 - return git_config_string((const char **)&data->v,
25 + return git_config_string(&data->v,
26 key, value);
27 } else if (data->list) {
28 string_list_append(data->list, p);
attr.c
+1 -1
@@ -25,7 +25,7 @@
25 #include "tree-walk.h"
26 #include "object-name.h"
27
28 -const char *git_attr_tree;
28 +char *git_attr_tree;
29
30 const char git_attr__true[] = "(builtin)true";
31 const char git_attr__false[] = "\0(builtin)false";
attr.h
+1 -1
@@ -236,6 +236,6 @@ const char *git_attr_global_file(void);
236 /* Return whether the system gitattributes file is enabled and should be used. */
237 int git_attr_system_is_enabled(void);
238
239 -extern const char *git_attr_tree;
239 +extern char *git_attr_tree;
240
241 #endif /* ATTR_H */
builtin/commit.c
+1 -1
@@ -133,7 +133,7 @@ static struct strvec trailer_args = STRVEC_INIT;
133 * is specified explicitly.
134 */
135 static enum commit_msg_cleanup_mode cleanup_mode;
136 -static const char *cleanup_arg;
136 +static char *cleanup_arg;
137
138 static enum commit_whence whence;
139 static int use_editor = 1, include_status = 1;
builtin/log.c
+6 -6
@@ -582,11 +582,11 @@ static int git_log_config(const char *var, const char *value,
582
583 if (!strcmp(var, "format.pretty")) {
584 FREE_AND_NULL(cfg->fmt_pretty);
585 - return git_config_string((const char **) &cfg->fmt_pretty, var, value);
585 + return git_config_string(&cfg->fmt_pretty, var, value);
586 }
587 if (!strcmp(var, "format.subjectprefix")) {
588 FREE_AND_NULL(cfg->fmt_patch_subject_prefix);
589 - return git_config_string((const char **) &cfg->fmt_patch_subject_prefix, var, value);
589 + return git_config_string(&cfg->fmt_patch_subject_prefix, var, value);
590 }
591 if (!strcmp(var, "format.filenamemaxlength")) {
592 cfg->fmt_patch_name_max = git_config_int(var, value, ctx->kvi);
@@ -602,7 +602,7 @@ static int git_log_config(const char *var, const char *value,
602 }
603 if (!strcmp(var, "log.date")) {
604 FREE_AND_NULL(cfg->default_date_mode);
605 - return git_config_string((const char **) &cfg->default_date_mode, var, value);
605 + return git_config_string(&cfg->default_date_mode, var, value);
606 }
607 if (!strcmp(var, "log.decorate")) {
608 cfg->decoration_style = parse_decoration_style(value);
@@ -1076,7 +1076,7 @@ static int git_format_config(const char *var, const char *value,
1076 }
1077 if (!strcmp(var, "format.suffix")) {
1078 FREE_AND_NULL(cfg->fmt_patch_suffix);
1079 - return git_config_string((const char **) &cfg->fmt_patch_suffix, var, value);
1079 + return git_config_string(&cfg->fmt_patch_suffix, var, value);
1080 }
1081 if (!strcmp(var, "format.to")) {
1082 if (!value)
@@ -1133,7 +1133,7 @@ static int git_format_config(const char *var, const char *value,
1133 }
1134 if (!strcmp(var, "format.signature")) {
1135 FREE_AND_NULL(cfg->signature);
1136 - return git_config_string((const char **) &cfg->signature, var, value);
1136 + return git_config_string(&cfg->signature, var, value);
1137 }
1138 if (!strcmp(var, "format.signaturefile")) {
1139 FREE_AND_NULL(cfg->signature_file);
@@ -1149,7 +1149,7 @@ static int git_format_config(const char *var, const char *value,
1149 }
1150 if (!strcmp(var, "format.outputdirectory")) {
1151 FREE_AND_NULL(cfg->config_output_directory);
1152 - return git_config_string((const char **) &cfg->config_output_directory, var, value);
1152 + return git_config_string(&cfg->config_output_directory, var, value);
1153 }
1154 if (!strcmp(var, "format.useautobase")) {
1155 if (value && !strcasecmp(value, "whenAble")) {
builtin/merge.c
+2 -2
@@ -100,7 +100,7 @@ static struct strategy all_strategy[] = {
100 { "subtree", NO_FAST_FORWARD | NO_TRIVIAL },
101 };
102
103 -static const char *pull_twohead, *pull_octopus;
103 +static char *pull_twohead, *pull_octopus;
104
105 enum ff_type {
106 FF_NO,
@@ -110,7 +110,7 @@ enum ff_type {
110
111 static enum ff_type fast_forward = FF_ALLOW;
112
113 -static const char *cleanup_arg;
113 +static char *cleanup_arg;
114 static enum commit_msg_cleanup_mode cleanup_mode;
115
116 static int option_parse_message(const struct option *opt,
builtin/rebase.c
+1 -1
@@ -83,7 +83,7 @@ static const char *action_names[] = {
83 struct rebase_options {
84 enum rebase_type type;
85 enum empty_type empty;
86 - const char *default_backend;
86 + char *default_backend;
87 const char *state_dir;
88 struct commit *upstream;
89 const char *upstream_name;
builtin/receive-pack.c
+1 -1
@@ -88,7 +88,7 @@ static struct strbuf push_cert = STRBUF_INIT;
88 static struct object_id push_cert_oid;
89 static struct signature_check sigcheck;
90 static const char *push_cert_nonce;
91 -static const char *cert_nonce_seed;
91 +static char *cert_nonce_seed;
92 static struct strvec hidden_refs = STRVEC_INIT;
93
94 static const char *NONCE_UNSOLICITED = "UNSOLICITED";
builtin/repack.c
+4 -4
@@ -48,10 +48,10 @@ static const char incremental_bitmap_conflict_error[] = N_(
48 );
49
50 struct pack_objects_args {
51 - const char *window;
52 - const char *window_memory;
53 - const char *depth;
54 - const char *threads;
51 + char *window;
52 + char *window_memory;
53 + char *depth;
54 + char *threads;
55 unsigned long max_pack_size;
56 int no_reuse_delta;
57 int no_reuse_object;
config.c
+3 -3
@@ -1338,7 +1338,7 @@ int git_config_bool(const char *name, const char *value)
1338 return v;
1339 }
1340
1341 -int git_config_string(const char **dest, const char *var, const char *value)
1341 +int git_config_string(char **dest, const char *var, const char *value)
1342 {
1343 if (!value)
1344 return config_error_nonbool(var);
@@ -1566,7 +1566,7 @@ static int git_default_core_config(const char *var, const char *value,
1566
1567 if (!strcmp(var, "core.checkroundtripencoding")) {
1568 FREE_AND_NULL(check_roundtrip_encoding);
1569 - return git_config_string((const char **) &check_roundtrip_encoding, var, value);
1569 + return git_config_string(&check_roundtrip_encoding, var, value);
1570 }
1571
1572 if (!strcmp(var, "core.notesref")) {
@@ -2418,7 +2418,7 @@ int git_configset_get_string(struct config_set *set, const char *key, char **des
2418 {
2419 const char *value;
2420 if (!git_configset_get_value(set, key, &value, NULL))
2421 - return git_config_string((const char **)dest, key, value);
2421 + return git_config_string(dest, key, value);
2422 else
2423 return 1;
2424 }
config.h
+1 -1
@@ -280,7 +280,7 @@ int git_config_bool(const char *, const char *);
280 * Allocates and copies the value string into the `dest` parameter; if no
281 * string is given, prints an error message and returns -1.
282 */
283 -int git_config_string(const char **, const char *, const char *);
283 +int git_config_string(char **, const char *, const char *);
284
285 /**
286 * Similar to `git_config_string`, but expands `~` or `~user` into the
convert.c
+3 -3
@@ -981,9 +981,9 @@ done:
981 static struct convert_driver {
982 const char *name;
983 struct convert_driver *next;
984 - const char *smudge;
985 - const char *clean;
986 - const char *process;
984 + char *smudge;
985 + char *clean;
986 + char *process;
987 int required;
988 } *user_convert, **user_convert_tail;
989
delta-islands.c
+1 -1
@@ -313,7 +313,7 @@ struct island_load_data {
313 size_t nr;
314 size_t alloc;
315 };
316 -static const char *core_island_name;
316 +static char *core_island_name;
317
318 static void free_config_regexes(struct island_load_data *ild)
319 {
diff.c
+4 -4
@@ -56,8 +56,8 @@ static int diff_color_moved_default;
56 static int diff_color_moved_ws_default;
57 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;
59 +static char *diff_word_regex_cfg;
60 +static char *external_diff_cmd_cfg;
61 static char *diff_order_file_cfg;
62 int diff_auto_refresh_index = 1;
63 static int diff_mnemonic_prefix;
@@ -412,11 +412,11 @@ int git_diff_ui_config(const char *var, const char *value,
412 }
413 if (!strcmp(var, "diff.srcprefix")) {
414 FREE_AND_NULL(diff_src_prefix);
415 - return git_config_string((const char **) &diff_src_prefix, var, value);
415 + return git_config_string(&diff_src_prefix, var, value);
416 }
417 if (!strcmp(var, "diff.dstprefix")) {
418 FREE_AND_NULL(diff_dst_prefix);
419 - return git_config_string((const char **) &diff_dst_prefix, var, value);
419 + return git_config_string(&diff_dst_prefix, var, value);
420 }
421 if (!strcmp(var, "diff.relative")) {
422 diff_relative = git_config_bool(var, value);
environment.c
+4 -4
@@ -42,8 +42,8 @@ int is_bare_repository_cfg = -1; /* unspecified */
42 int warn_ambiguous_refs = 1;
43 int warn_on_object_refname_ambiguity = 1;
44 int repository_format_precious_objects;
45 -const char *git_commit_encoding;
46 -const char *git_log_output_encoding;
45 +char *git_commit_encoding;
46 +char *git_log_output_encoding;
47 char *apply_default_whitespace;
48 char *apply_default_ignorewhitespace;
49 char *git_attributes_file;
@@ -58,8 +58,8 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
58 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
59 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;
61 +char *editor_program;
62 +char *askpass_program;
63 char *excludes_file;
64 enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
65 enum eol core_eol = EOL_UNSET;
environment.h
+4 -4
@@ -224,11 +224,11 @@ int odb_pack_keep(const char *name);
224 const char *get_log_output_encoding(void);
225 const char *get_commit_output_encoding(void);
226
227 -extern const char *git_commit_encoding;
228 -extern const char *git_log_output_encoding;
227 +extern char *git_commit_encoding;
228 +extern char *git_log_output_encoding;
229
230 -extern const char *editor_program;
231 -extern const char *askpass_program;
230 +extern char *editor_program;
231 +extern char *askpass_program;
232 extern char *excludes_file;
233
234 /*
gpg-interface.c
+2 -2
@@ -27,14 +27,14 @@ static void gpg_interface_lazy_init(void)
27 }
28
29 static char *configured_signing_key;
30 -static const char *ssh_default_key_command;
30 +static 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 {
36 const char *name;
37 - const char *program;
37 + char *program;
38 const char **verify_args;
39 const char **sigs;
40 int (*verify_signed_buffer)(struct signature_check *sigc,
http.c
+12 -12
@@ -38,11 +38,11 @@ char curl_errorstr[CURL_ERROR_SIZE];
38
39 static int curl_ssl_verify = -1;
40 static int curl_ssl_try;
41 -static const char *curl_http_version = NULL;
41 +static char *curl_http_version;
42 static char *ssl_cert;
43 static char *ssl_cert_type;
44 -static const char *ssl_cipherlist;
45 -static const char *ssl_version;
44 +static char *ssl_cipherlist;
45 +static char *ssl_version;
46 static struct {
47 const char *name;
48 long ssl_version;
@@ -95,7 +95,7 @@ static struct {
95 */
96 };
97 #ifdef CURLGSSAPI_DELEGATION_FLAG
98 -static const char *curl_deleg;
98 +static char *curl_deleg;
99 static struct {
100 const char *name;
101 long curl_deleg_param;
@@ -383,11 +383,11 @@ static int http_options(const char *var, const char *value,
383 if (!strcmp("http.sslcert", var))
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);
386 + return git_config_string(&ssl_cert_type, var, value);
387 if (!strcmp("http.sslkey", var))
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);
390 + return git_config_string(&ssl_key_type, var, value);
391 if (!strcmp("http.sslcapath", var))
392 return git_config_pathname(&ssl_capath, var, value);
393 if (!strcmp("http.sslcainfo", var))
@@ -440,19 +440,19 @@ static int http_options(const char *var, const char *value,
440 return 0;
441 }
442 if (!strcmp("http.proxy", var))
443 - return git_config_string((const char **)&curl_http_proxy, var, value);
443 + return git_config_string(&curl_http_proxy, var, value);
444
445 if (!strcmp("http.proxyauthmethod", var))
446 - return git_config_string((const char **)&http_proxy_authmethod, var, value);
446 + return git_config_string(&http_proxy_authmethod, var, value);
447
448 if (!strcmp("http.proxysslcert", var))
449 - return git_config_string((const char **)&http_proxy_ssl_cert, var, value);
449 + return git_config_string(&http_proxy_ssl_cert, var, value);
450
451 if (!strcmp("http.proxysslkey", var))
452 - return git_config_string((const char **)&http_proxy_ssl_key, var, value);
452 + return git_config_string(&http_proxy_ssl_key, var, value);
453
454 if (!strcmp("http.proxysslcainfo", var))
455 - return git_config_string((const char **)&http_proxy_ssl_ca_info, var, value);
455 + return git_config_string(&http_proxy_ssl_ca_info, var, value);
456
457 if (!strcmp("http.proxysslcertpasswordprotected", var)) {
458 proxy_ssl_cert_password_required = git_config_bool(var, value);
@@ -476,7 +476,7 @@ static int http_options(const char *var, const char *value,
476 }
477
478 if (!strcmp("http.useragent", var))
479 - return git_config_string((const char **)&user_agent, var, value);
479 + return git_config_string(&user_agent, var, value);
480
481 if (!strcmp("http.emptyauth", var)) {
482 if (value && !strcmp("auto", value))
imap-send.c
+6 -6
@@ -70,16 +70,16 @@ static char *next_arg(char **);
70
71 struct imap_server_conf {
72 const char *name;
73 - const char *tunnel;
74 - const char *host;
73 + char *tunnel;
74 + char *host;
75 int port;
76 - const char *folder;
77 - const char *user;
78 - const char *pass;
76 + char *folder;
77 + char *user;
78 + char *pass;
79 int use_ssl;
80 int ssl_verify;
81 int use_html;
82 - const char *auth_method;
82 + char *auth_method;
83 };
84
85 static struct imap_server_conf server = {
mailmap.c
+1 -1
@@ -7,7 +7,7 @@
7 #include "setup.h"
8
9 char *git_mailmap_file;
10 -const char *git_mailmap_blob;
10 +char *git_mailmap_blob;
11
12 struct mailmap_info {
13 char *name;
mailmap.h
+1 -1
@@ -4,7 +4,7 @@
4 struct string_list;
5
6 extern char *git_mailmap_file;
7 -extern const char *git_mailmap_blob;
7 +extern char *git_mailmap_blob;
8
9 int read_mailmap(struct string_list *map);
10 void clear_mailmap(struct string_list *map);
merge-ll.c
+3 -3
@@ -27,9 +27,9 @@ typedef enum ll_merge_result (*ll_merge_fn)(const struct ll_merge_driver *,
27
28 struct ll_merge_driver {
29 const char *name;
30 - const char *description;
30 + char *description;
31 ll_merge_fn fn;
32 - const char *recursive;
32 + char *recursive;
33 struct ll_merge_driver *next;
34 char *cmdline;
35 };
@@ -268,7 +268,7 @@ static enum ll_merge_result ll_ext_merge(const struct ll_merge_driver *fn,
268 * merge.default and merge.driver configuration items
269 */
270 static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
271 -static const char *default_ll_merge;
271 +static char *default_ll_merge;
272
273 static int read_merge_config(const char *var, const char *value,
274 const struct config_context *ctx UNUSED,
pager.c
+1 -1
@@ -13,7 +13,7 @@ int pager_use_color = 1;
13 #endif
14
15 static struct child_process pager_process;
16 -static const char *pager_program;
16 +static char *pager_program;
17
18 /* Is the value coming back from term_columns() just a guess? */
19 static int term_columns_guessed;
pretty.c
+9 -5
@@ -62,7 +62,7 @@ static int git_pretty_formats_config(const char *var, const char *value,
62 {
63 struct cmt_fmt_map *commit_format = NULL;
64 const char *name;
65 - const char *fmt;
65 + char *fmt;
66 int i;
67
68 if (!skip_prefix(var, "pretty.", &name))
@@ -93,13 +93,17 @@ static int git_pretty_formats_config(const char *var, const char *value,
93 if (git_config_string(&fmt, var, value))
94 return -1;
95
96 - if (skip_prefix(fmt, "format:", &fmt))
96 + if (skip_prefix(fmt, "format:", &commit_format->user_format)) {
97 commit_format->is_tformat = 0;
98 - else if (skip_prefix(fmt, "tformat:", &fmt) || strchr(fmt, '%'))
98 + } else if (skip_prefix(fmt, "tformat:", &commit_format->user_format)) {
99 commit_format->is_tformat = 1;
100 - else
100 + } else if (strchr(fmt, '%')) {
101 + commit_format->is_tformat = 1;
102 + commit_format->user_format = fmt;
103 + } else {
104 commit_format->is_alias = 1;
102 - commit_format->user_format = fmt;
105 + commit_format->user_format = fmt;
106 + }
107
108 return 0;
109 }
promisor-remote.h
+1 -1
@@ -13,7 +13,7 @@ struct object_id;
13 */
14 struct promisor_remote {
15 struct promisor_remote *next;
16 - const char *partial_clone_filter;
16 + char *partial_clone_filter;
17 const char name[FLEX_ARRAY];
18 };
19
remote.c
+10 -10
@@ -428,29 +428,29 @@ static int handle_config(const char *key, const char *value,
428 else if (!strcmp(subkey, "prunetags"))
429 remote->prune_tags = git_config_bool(key, value);
430 else if (!strcmp(subkey, "url")) {
431 - const char *v;
431 + char *v;
432 if (git_config_string(&v, key, value))
433 return -1;
434 add_url(remote, v);
435 } else if (!strcmp(subkey, "pushurl")) {
436 - const char *v;
436 + char *v;
437 if (git_config_string(&v, key, value))
438 return -1;
439 add_pushurl(remote, v);
440 } else if (!strcmp(subkey, "push")) {
441 - const char *v;
441 + char *v;
442 if (git_config_string(&v, key, value))
443 return -1;
444 refspec_append(&remote->push, v);
445 - free((char *)v);
445 + free(v);
446 } else if (!strcmp(subkey, "fetch")) {
447 - const char *v;
447 + char *v;
448 if (git_config_string(&v, key, value))
449 return -1;
450 refspec_append(&remote->fetch, v);
451 - free((char *)v);
451 + free(v);
452 } else if (!strcmp(subkey, "receivepack")) {
453 - const char *v;
453 + char *v;
454 if (git_config_string(&v, key, value))
455 return -1;
456 if (!remote->receivepack)
@@ -458,7 +458,7 @@ static int handle_config(const char *key, const char *value,
458 else
459 error(_("more than one receivepack given, using the first"));
460 } else if (!strcmp(subkey, "uploadpack")) {
461 - const char *v;
461 + char *v;
462 if (git_config_string(&v, key, value))
463 return -1;
464 if (!remote->uploadpack)
@@ -471,10 +471,10 @@ static int handle_config(const char *key, const char *value,
471 else if (!strcmp(value, "--tags"))
472 remote->fetch_tags = 2;
473 } else if (!strcmp(subkey, "proxy")) {
474 - return git_config_string((const char **)&remote->http_proxy,
474 + return git_config_string(&remote->http_proxy,
475 key, value);
476 } else if (!strcmp(subkey, "proxyauthmethod")) {
477 - return git_config_string((const char **)&remote->http_proxy_authmethod,
477 + return git_config_string(&remote->http_proxy_authmethod,
478 key, value);
479 } else if (!strcmp(subkey, "vcs")) {
480 return git_config_string(&remote->foreign_vcs, key, value);
remote.h
+4 -4
@@ -46,7 +46,7 @@ struct remote_state {
46 struct hashmap branches_hash;
47
48 struct branch *current_branch;
49 - const char *pushremote_name;
49 + char *pushremote_name;
50
51 struct rewrites rewrites;
52 struct rewrites rewrites_push;
@@ -65,7 +65,7 @@ struct remote {
65
66 int origin, configured_in_repo;
67
68 - const char *foreign_vcs;
68 + char *foreign_vcs;
69
70 /* An array of all of the url_nr URLs configured for the remote */
71 const char **url;
@@ -309,9 +309,9 @@ struct branch {
309 const char *refname;
310
311 /* The name of the remote listed in the configuration. */
312 - const char *remote_name;
312 + char *remote_name;
313
314 - const char *pushremote_name;
314 + char *pushremote_name;
315
316 /* An array of the "merge" lines in the configuration. */
317 const char **merge_name;
sequencer.c
+1 -1
@@ -306,7 +306,7 @@ static int git_sequencer_config(const char *k, const char *v,
306 }
307
308 if (!opts->default_strategy && !strcmp(k, "pull.twohead")) {
309 - int ret = git_config_string((const char**)&opts->default_strategy, k, v);
309 + int ret = git_config_string(&opts->default_strategy, k, v);
310 if (ret == 0) {
311 /*
312 * pull.twohead is allowed to be multi-valued; we only
upload-pack.c
+1 -1
@@ -94,7 +94,7 @@ struct upload_pack_data {
94
95 struct packet_writer writer;
96
97 - const char *pack_objects_hook;
97 + char *pack_objects_hook;
98
99 unsigned stateless_rpc : 1; /* v0 only */
100 unsigned no_done : 1; /* v0 only */
userdiff.h
+6 -6
@@ -7,19 +7,19 @@ struct index_state;
7 struct repository;
8
9 struct userdiff_funcname {
10 - const char *pattern;
10 + char *pattern;
11 int cflags;
12 };
13
14 struct userdiff_driver {
15 const char *name;
16 - const char *external;
17 - const char *algorithm;
16 + char *external;
17 + char *algorithm;
18 int binary;
19 struct userdiff_funcname funcname;
20 - const char *word_regex;
21 - const char *word_regex_multi_byte;
22 - const char *textconv;
20 + char *word_regex;
21 + char *word_regex_multi_byte;
22 + char *textconv;
23 struct notes_cache *textconv_cache;
24 int textconv_want_cache;
25 };