g10: Don't leak memory if we fail to initialize a new database handle.
[gnupg.git] / g10 / free-packet.c
index 47d89ee..670f256 100644 (file)
 #include <assert.h>
 
 #include "gpg.h"
+#include "util.h"
 #include "packet.h"
 #include "../common/iobuf.h"
-#include "util.h"
-#include "cipher.h"
-#include "options.h" 
+#include "options.h"
+
+
+/* This is mpi_copy with a fix for opaque MPIs which store a NULL
+   pointer.  This will also be fixed in Libggcrypt 1.7.0.  */
+static gcry_mpi_t
+my_mpi_copy (gcry_mpi_t a)
+{
+  if (a
+      && gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
+      && !gcry_mpi_get_opaque (a, NULL))
+    return NULL;
+
+  return gcry_mpi_copy (a);
+}
 
 
 void
@@ -79,7 +92,7 @@ void
 release_public_key_parts (PKT_public_key *pk)
 {
   int n, i;
-  
+
   if (pk->seckey_info)
     n = pubkey_get_nskey (pk->pubkey_algo);
   else
@@ -112,15 +125,24 @@ release_public_key_parts (PKT_public_key *pk)
       pk->revkey=NULL;
       pk->numrevkeys=0;
     }
-
+  if (pk->serialno)
+    {
+      xfree (pk->serialno);
+      pk->serialno = NULL;
+    }
 }
 
 
+/* Free an allocated public key structure including all parts.
+   Passing NULL is allowed.  */
 void
 free_public_key (PKT_public_key *pk)
 {
-  release_public_key_parts (pk);
-  xfree(pk);
+  if (pk)
+    {
+      release_public_key_parts (pk);
+      xfree(pk);
+    }
 }
 
 
@@ -139,7 +161,7 @@ cp_subpktarea (subpktarea_t *s )
 }
 
 /*
- * Return a copy of the preferences 
+ * Return a copy of the preferences
  */
 prefitem_t *
 copy_prefs (const prefitem_t *prefs)
@@ -149,7 +171,7 @@ copy_prefs (const prefitem_t *prefs)
 
     if (!prefs)
         return NULL;
-    
+
     for (n=0; prefs[n].type; n++)
         ;
     new = xmalloc ( sizeof (*new) * (n+1));
@@ -171,22 +193,22 @@ PKT_public_key *
 copy_public_key (PKT_public_key *d, PKT_public_key *s)
 {
   int n, i;
-  
+
   if (!d)
     d = xmalloc (sizeof *d);
   memcpy (d, s, sizeof *d);
-  d->seckey_info = NULL; 
+  d->seckey_info = NULL;
   d->user_id = scopy_user_id (s->user_id);
   d->prefs = copy_prefs (s->prefs);
 
   n = pubkey_get_npkey (s->pubkey_algo);
   i = 0;
   if (!n)
-    d->pkey[i++] = mpi_copy (s->pkey[0]);
-  else 
+    d->pkey[i++] = my_mpi_copy (s->pkey[0]);
+  else
     {
       for (; i < n; i++ )
-        d->pkey[i] = mpi_copy( s->pkey[i] );
+        d->pkey[i] = my_mpi_copy (s->pkey[i]);
     }
   for (; i < PUBKEY_MAX_NSKEY; i++)
     d->pkey[i] = NULL;
@@ -209,7 +231,7 @@ static pka_info_t *
 cp_pka_info (const pka_info_t *s)
 {
   pka_info_t *d = xmalloc (sizeof *s + strlen (s->email));
-  
+
   d->valid = s->valid;
   d->checked = s->checked;
   d->uri = s->uri? xstrdup (s->uri):NULL;
@@ -229,10 +251,10 @@ copy_signature( PKT_signature *d, PKT_signature *s )
     memcpy( d, s, sizeof *d );
     n = pubkey_get_nsig( s->pubkey_algo );
     if( !n )
-       d->data[0] = mpi_copy(s->data[0]);
+       d->data[0] = my_mpi_copy(s->data[0]);
     else {
        for(i=0; i < n; i++ )
-           d->data[i] = mpi_copy( s->data[i] );
+           d->data[i] = my_mpi_copy( s->data[i] );
     }
     d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL;
     d->hashed = cp_subpktarea (s->hashed);
@@ -412,11 +434,14 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
        return -1;
 
     n = pubkey_get_npkey( b->pubkey_algo );
-    if( !n )
-       return -1; /* can't compare due to unknown algorithm */
-    for(i=0; i < n; i++ ) {
-       if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
-           return -1;
+    if( !n ) { /* unknown algorithm, rest is in opaque MPI */
+       if( mpi_cmp( a->pkey[0], b->pkey[0] ) )
+           return -1; /* can't compare due to unknown algorithm */
+    } else {
+       for(i=0; i < n; i++ ) {
+           if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
+               return -1;
+       }
     }
 
     return 0;