gpg locks up with certain key servers
David Shaw
dshaw at jabberwocky.com
Sun Aug 12 01:57:58 CEST 2007
On Fri, Aug 10, 2007 at 12:29:05AM -0400, David Shaw wrote:
> GPG isn't actually locking up here - it's just very slow. The
> reason for the slow import of that key is the need for GPG to detect
> and remove the duplicated packets. On my machine, it takes just
> under an hour to process that key.
>
> The algorithm currently in GPG for detecting and repairing the
> duplication is not as efficient as it could be. I'll have a look at
> it and see what I can do.
Try this patch. It can import the corrupt key in around 5 seconds on
my machine.
David
-------------- next part --------------
Index: import.c
===================================================================
--- import.c (revision 4557)
+++ import.c (working copy)
@@ -1644,11 +1644,108 @@
* It may happen that the imported keyblock has duplicated user IDs.
* We check this here and collapse those user IDs together with their
* sigs into one.
- * Returns: True if the keyblock hash changed.
+ * Returns: True if the keyblock has changed.
*/
int
collapse_uids( KBNODE *keyblock )
{
+ KBNODE uid1;
+ int any=0;
+
+ for(uid1=*keyblock;uid1;uid1=uid1->next)
+ {
+ KBNODE uid2;
+
+ if(uid1->pkt->pkttype!=PKT_USER_ID)
+ continue;
+
+ for(uid2=uid1->next;uid2;uid2=uid2->next)
+ {
+ if(uid2->pkt->pkttype!=PKT_USER_ID)
+ continue;
+
+ if(cmp_user_ids(uid1->pkt->pkt.user_id,
+ uid2->pkt->pkt.user_id)==0)
+ {
+ /* We have a duplicated uid */
+ KBNODE sig1,last;
+
+ any=1;
+
+ /* Now take uid2's signatures, and attach them to
+ uid1 */
+ for(last=uid2;last->next;last=last->next)
+ {
+ if(last->next->pkt->pkttype==PKT_USER_ID
+ || last->next->pkt->pkttype==PKT_PUBLIC_SUBKEY
+ || last->next->pkt->pkttype==PKT_SECRET_SUBKEY)
+ break;
+ }
+
+ /* Snip out uid2 */
+ (find_prev_kbnode(*keyblock,uid2,0))->next=last->next;
+
+ /* Now put uid2 in place as part of uid1 */
+ last->next=uid1->next;
+ uid1->next=uid2;
+ remove_kbnode(keyblock,uid2);
+
+ /* Now dedupe uid1 */
+ for(sig1=uid1->next;sig1;sig1=sig1->next)
+ {
+ KBNODE sig2;
+
+ if(sig1->pkt->pkttype==PKT_USER_ID
+ || sig1->pkt->pkttype==PKT_PUBLIC_SUBKEY
+ || sig1->pkt->pkttype==PKT_SECRET_SUBKEY)
+ break;
+
+ if(sig1->pkt->pkttype!=PKT_SIGNATURE)
+ continue;
+
+ for(sig2=sig1->next,last=sig1;sig2;last=sig2,sig2=sig2->next)
+ {
+ if(sig2->pkt->pkttype==PKT_USER_ID
+ || sig2->pkt->pkttype==PKT_PUBLIC_SUBKEY
+ || sig2->pkt->pkttype==PKT_SECRET_SUBKEY)
+ break;
+
+ if(sig2->pkt->pkttype!=PKT_SIGNATURE)
+ continue;
+
+ if(cmp_signatures(sig1->pkt->pkt.signature,
+ sig2->pkt->pkt.signature)==0)
+ {
+ /* We have a match, so delete the second
+ signature */
+ remove_kbnode(&uid1,sig2);
+ sig2=last;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(any && !opt.quiet)
+ {
+ const char *key="???";
+
+ if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) )
+ key=keystr_from_pk(uid1->pkt->pkt.public_key);
+ else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) )
+ key=keystr_from_sk(uid1->pkt->pkt.secret_key);
+
+ log_info(_("key %s: duplicated user ID detected - merged\n"),key);
+ }
+
+ return any;
+}
+
+#if 0
+int
+collapse_uids( KBNODE *keyblock )
+{
KBNODE n, n2;
int in_uid;
int any=0;
@@ -1729,6 +1826,7 @@
return 1;
}
+#endif
/* Check for a 0x20 revocation from a revocation key that is not
present. This may be called without the benefit of merge_xxxx so
More information about the Gnupg-devel
mailing list