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;
   }
 

Reply via email to