changeset: 6398:58a9dbfd0d25 user: Kevin McCarthy <ke...@8t8.us> date: Sat Jan 17 14:34:13 2015 -0800 link: http://dev.mutt.org/hg/mutt/rev/58a9dbfd0d25
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). diffs (247 lines): diff -r cc7903944687 -r 58a9dbfd0d25 crypt-gpgme.c --- a/crypt-gpgme.c Sat Jan 17 14:42:28 2015 -0800 +++ b/crypt-gpgme.c Sat Jan 17 14:34:13 2015 -0800 @@ -248,12 +248,19 @@ 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 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 @@ { 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 @@ 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 @@ 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 @@ if (set_signer (ctx, use_smime)) { gpgme_data_release (signature); + gpgme_data_release (message); gpgme_release (ctx); return NULL; } @@ -962,13 +994,13 @@ 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 @@ 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 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1421,7 +1453,7 @@ } if (key != signature_key) - gpgme_key_release (key); + gpgme_key_unref (key); } return anybad ? 1 : anywarn ? 2 : 0; @@ -1462,6 +1494,9 @@ 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 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; } @@ -1967,7 +2002,7 @@ 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 @@ FREE (&tmpfname); } } + gpgme_data_release (plaintext); gpgme_release (ctx); } @@ -2405,6 +2441,7 @@ state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); } + gpgme_data_release (armored_data); if (pgpout) { safe_fclose (&pgpout); @@ -3515,7 +3552,7 @@ { 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 @@ } leave: - gpgme_key_release (k); + gpgme_key_unref (k); gpgme_release (listctx); safe_fclose (&fp); mutt_clear_error (); @@ -3706,12 +3743,14 @@ { 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 @@ { 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 @@ if (signature_key) { - gpgme_key_release (signature_key); + gpgme_key_unref (signature_key); signature_key = NULL; }