Skip to content

Commit b8849e2

Browse files
pks-tgitster
authored andcommitted
gpg-interface: fix misdesigned signing key interfaces
The interfaces to retrieve signing keys and their IDs are misdesigned as they return string constants even though they indeed allocate memory, which leads to memory leaks. Refactor the code to instead always return allocated strings and let the callers free them accordingly. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 49d47eb commit b8849e2

File tree

6 files changed

+30
-19
lines changed

6 files changed

+30
-19
lines changed

builtin/tag.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
160160
const struct git_hash_algo *compat = the_repository->compat_hash_algo;
161161
struct strbuf sig = STRBUF_INIT, compat_sig = STRBUF_INIT;
162162
struct strbuf compat_buf = STRBUF_INIT;
163-
const char *keyid = get_signing_key();
163+
char *keyid = get_signing_key();
164164
int ret = -1;
165165

166166
if (sign_buffer(buffer, &sig, keyid))
@@ -190,6 +190,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
190190
strbuf_release(&sig);
191191
strbuf_release(&compat_sig);
192192
strbuf_release(&compat_buf);
193+
free(keyid);
193194
return ret;
194195
}
195196

commit.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -1150,11 +1150,14 @@ int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct gi
11501150

11511151
static int sign_commit_to_strbuf(struct strbuf *sig, struct strbuf *buf, const char *keyid)
11521152
{
1153+
char *keyid_to_free = NULL;
1154+
int ret = 0;
11531155
if (!keyid || !*keyid)
1154-
keyid = get_signing_key();
1156+
keyid = keyid_to_free = get_signing_key();
11551157
if (sign_buffer(buf, sig, keyid))
1156-
return -1;
1157-
return 0;
1158+
ret = -1;
1159+
free(keyid_to_free);
1160+
return ret;
11581161
}
11591162

11601163
int parse_signed_commit(const struct commit *commit,

gpg-interface.c

+15-11
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ struct gpg_format {
4545
size_t signature_size);
4646
int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
4747
const char *signing_key);
48-
const char *(*get_default_key)(void);
49-
const char *(*get_key_id)(void);
48+
char *(*get_default_key)(void);
49+
char *(*get_key_id)(void);
5050
};
5151

5252
static const char *openpgp_verify_args[] = {
@@ -86,9 +86,9 @@ static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
8686
static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
8787
const char *signing_key);
8888

89-
static const char *get_default_ssh_signing_key(void);
89+
static char *get_default_ssh_signing_key(void);
9090

91-
static const char *get_ssh_key_id(void);
91+
static char *get_ssh_key_id(void);
9292

9393
static struct gpg_format gpg_format[] = {
9494
{
@@ -847,7 +847,7 @@ static char *get_ssh_key_fingerprint(const char *signing_key)
847847
}
848848

849849
/* Returns the first public key from an ssh-agent to use for signing */
850-
static const char *get_default_ssh_signing_key(void)
850+
static char *get_default_ssh_signing_key(void)
851851
{
852852
struct child_process ssh_default_key = CHILD_PROCESS_INIT;
853853
int ret = -1;
@@ -899,12 +899,16 @@ static const char *get_default_ssh_signing_key(void)
899899
return default_key;
900900
}
901901

902-
static const char *get_ssh_key_id(void) {
903-
return get_ssh_key_fingerprint(get_signing_key());
902+
static char *get_ssh_key_id(void)
903+
{
904+
char *signing_key = get_signing_key();
905+
char *key_id = get_ssh_key_fingerprint(signing_key);
906+
free(signing_key);
907+
return key_id;
904908
}
905909

906910
/* Returns a textual but unique representation of the signing key */
907-
const char *get_signing_key_id(void)
911+
char *get_signing_key_id(void)
908912
{
909913
gpg_interface_lazy_init();
910914

@@ -916,17 +920,17 @@ const char *get_signing_key_id(void)
916920
return get_signing_key();
917921
}
918922

919-
const char *get_signing_key(void)
923+
char *get_signing_key(void)
920924
{
921925
gpg_interface_lazy_init();
922926

923927
if (configured_signing_key)
924-
return configured_signing_key;
928+
return xstrdup(configured_signing_key);
925929
if (use_format->get_default_key) {
926930
return use_format->get_default_key();
927931
}
928932

929-
return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
933+
return xstrdup(git_committer_info(IDENT_STRICT | IDENT_NO_DATE));
930934
}
931935

932936
const char *gpg_trust_level_to_str(enum signature_trust_level level)

gpg-interface.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
8080
const char *gpg_trust_level_to_str(enum signature_trust_level level);
8181

8282
void set_signing_key(const char *);
83-
const char *get_signing_key(void);
83+
char *get_signing_key(void);
8484

8585
/*
8686
* Returns a textual unique representation of the signing key in use
8787
* Either a GPG KeyID or a SSH Key Fingerprint
8888
*/
89-
const char *get_signing_key_id(void);
89+
char *get_signing_key_id(void);
9090
int check_signature(struct signature_check *sigc,
9191
const char *signature, size_t slen);
9292
void print_signature_buffer(const struct signature_check *sigc,

send-pack.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ static int generate_push_cert(struct strbuf *req_buf,
348348
{
349349
const struct ref *ref;
350350
struct string_list_item *item;
351-
char *signing_key_id = xstrdup(get_signing_key_id());
351+
char *signing_key_id = get_signing_key_id();
352+
char *signing_key = get_signing_key();
352353
const char *cp, *np;
353354
struct strbuf cert = STRBUF_INIT;
354355
int update_seen = 0;
@@ -381,7 +382,7 @@ static int generate_push_cert(struct strbuf *req_buf,
381382
if (!update_seen)
382383
goto free_return;
383384

384-
if (sign_buffer(&cert, &cert, get_signing_key()))
385+
if (sign_buffer(&cert, &cert, signing_key))
385386
die(_("failed to sign the push certificate"));
386387

387388
packet_buf_write(req_buf, "push-cert%c%s", 0, cap_string);
@@ -394,6 +395,7 @@ static int generate_push_cert(struct strbuf *req_buf,
394395

395396
free_return:
396397
free(signing_key_id);
398+
free(signing_key);
397399
strbuf_release(&cert);
398400
return update_seen;
399401
}

t/t5534-push-signed.sh

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='signed push'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910
. "$TEST_DIRECTORY"/lib-gpg.sh
1011

0 commit comments

Comments
 (0)