From: Kevin McCarthy Date: Sat, 17 Jan 2015 22:34:13 +0000 (-0800) Subject: Fix some context, data, and key memory leaks in gpgme. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b42d4356e6aa19673167e7f426fa5519e3f7e042;p=mutt Fix some context, data, and key memory leaks in gpgme. The context and data cleanup just involved adding missing gpgme_release() and gpgme_data_release() calls in a few places. The key usage was a little more involved: * Fix crypt_free_key(). It wasn't freeing the key passed in, and didn't work properly if multiple keys were passed in. It also was missing a call to gpgme_key_unref(). * Add free_recipient_set() to properly unref all the keys before freeing the array. * Fix get_candidates() to ref keys added to the crypt_key_t list, and unref the keys returned by gpgme_op_keylist_next(). * Change usages of gpgme_key_release() to gpgme_key_unref(). The former was deprecated in gpgme version 0.4.1 (2003-06-06). --- diff --git a/crypt-gpgme.c b/crypt-gpgme.c index 44abe872..4f2af940 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -248,12 +248,19 @@ static crypt_key_t *crypt_copy_key (crypt_key_t *key) to NULL. */ static void crypt_free_key (crypt_key_t **keylist) { + crypt_key_t *k; + + if (!keylist) + return; + while (*keylist) - { - crypt_key_t *k = (*keylist)->next; - FREE (&k); - *keylist = k; - } + { + k = *keylist; + *keylist = (*keylist)->next; + + gpgme_key_unref (k->kobj); + FREE (&k); + } } /* Return trute when key K is valid. */ @@ -556,6 +563,28 @@ static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp) } +static void free_recipient_set (gpgme_key_t **p_rset) +{ + gpgme_key_t *rset, k; + + if (!p_rset) + return; + + rset = *p_rset; + if (!rset) + return; + + while (*rset) + { + k = *rset; + gpgme_key_unref (k); + rset++; + } + + FREE (p_rset); /* __FREE_CHECKED__ */ +} + + /* Create a GpgmeRecipientSet from the keys in the string KEYLIST. The keys must be space delimited. */ static gpgme_key_t *create_recipient_set (const char *keylist, @@ -608,7 +637,9 @@ static gpgme_key_t *create_recipient_set (const char *keylist, { mutt_error (_("error adding recipient `%s': %s\n"), buf, gpgme_strerror (err)); - FREE (&rset); + rset[rset_n] = NULL; + free_recipient_set (&rset); + gpgme_release (context); return NULL; } } @@ -651,8 +682,8 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime) err = gpgme_op_keylist_next (listctx, &key2); if (!err) { - gpgme_key_release (key); - gpgme_key_release (key2); + gpgme_key_unref (key); + gpgme_key_unref (key2); gpgme_release (listctx); mutt_error (_("ambiguous specification of secret key `%s'\n"), signid); @@ -663,7 +694,7 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime) gpgme_signers_clear (ctx); err = gpgme_signers_add (ctx, key); - gpgme_key_release (key); + gpgme_key_unref (key); if (err) { mutt_error (_("error setting secret key `%s': %s\n"), @@ -834,6 +865,7 @@ static BODY *sign_message (BODY *a, int use_smime) if (set_signer (ctx, use_smime)) { gpgme_data_release (signature); + gpgme_data_release (message); gpgme_release (ctx); return NULL; } @@ -962,13 +994,13 @@ BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign) plaintext = body_to_data_object (a, 0); if (!plaintext) { - FREE (&rset); + free_recipient_set (&rset); return NULL; } outfile = encrypt_gpgme_object (plaintext, rset, 0, sign); gpgme_data_release (plaintext); - FREE (&rset); + free_recipient_set (&rset); if (!outfile) return NULL; @@ -1021,13 +1053,13 @@ BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist) plaintext = body_to_data_object (a, 0); if (!plaintext) { - FREE (&rset); + free_recipient_set (&rset); return NULL; } outfile = encrypt_gpgme_object (plaintext, rset, 1, 0); gpgme_data_release (plaintext); - FREE (&rset); + free_recipient_set (&rset); if (!outfile) return NULL; @@ -1343,7 +1375,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s) if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1421,7 +1453,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s) } if (key != signature_key) - gpgme_key_release (key); + gpgme_key_unref (key); } return anybad ? 1 : anywarn ? 2 : 0; @@ -1462,6 +1494,9 @@ static int verify_one (BODY *sigbdy, STATE *s, state_attach_puts (_("[-- Begin signature information --]\n"), s); err = gpgme_op_verify (ctx, signature, message, NULL); + gpgme_data_release (message); + gpgme_data_release (signature); + mutt_need_hard_redraw (); if (err) { @@ -1479,7 +1514,7 @@ static int verify_one (BODY *sigbdy, STATE *s, if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1967,7 +2002,7 @@ static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun) subkey = subkey->next; more = 1; } - gpgme_key_release (key); + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) { @@ -2354,6 +2389,7 @@ int pgp_gpgme_application_handler (BODY *m, STATE *s) FREE (&tmpfname); } } + gpgme_data_release (plaintext); gpgme_release (ctx); } @@ -2405,6 +2441,7 @@ int pgp_gpgme_application_handler (BODY *m, STATE *s) state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); } + gpgme_data_release (armored_data); if (pgpout) { safe_fclose (&pgpout); @@ -3515,7 +3552,7 @@ verify_key (crypt_key_t *key) { putc ('\n', fp); err = gpgme_op_keylist_start (listctx, s, 0); - gpgme_key_release (k); + gpgme_key_unref (k); k = NULL; if (!err) err = gpgme_op_keylist_next (listctx, &k); @@ -3538,7 +3575,7 @@ verify_key (crypt_key_t *key) } leave: - gpgme_key_release (k); + gpgme_key_unref (k); gpgme_release (listctx); safe_fclose (&fp); mutt_clear_error (); @@ -3706,12 +3743,14 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) { k = safe_calloc (1, sizeof *k); k->kobj = key; + gpgme_key_ref (k->kobj); k->idx = idx; k->uid = uid->uid; k->flags = flags; *kend = k; kend = &k->next; } + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); @@ -3747,12 +3786,14 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) { k = safe_calloc (1, sizeof *k); k->kobj = key; + gpgme_key_ref (k->kobj); k->idx = idx; k->uid = uid->uid; k->flags = flags; *kend = k; kend = &k->next; } + gpgme_key_unref (key); } if (gpg_err_code (err) != GPG_ERR_EOF) mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); @@ -4596,7 +4637,7 @@ static int verify_sender (HEADER *h, gpgme_protocol_t protocol) if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; }