keyring search regression in master

Neal H. Walfield neal at
Wed Nov 11 18:34:00 CET 2015

At Wed, 11 Nov 2015 11:22:22 +0100,
Neal H. Walfield wrote:
> At Wed, 11 Nov 2015 15:57:28 +0900,
> NIIBE Yutaka wrote:
> > On 2015-11-11 at 12:11 +0900, NIIBE Yutaka wrote:
> > > # List with LONG-ID doesn't work
> > > $ gpg2 --homedir=/tmp/gpghome --list-key 79A79093084239CF
> > > gpg: error reading key: No public key
> > 
> > I think I located the problem, but I don't know how to fix.
> > 
> > It was introduced by the function check_user_ids.  It searches once,
> > and then, in the line 2198, it searches again.
> FWIW, this is not a bug.  The second search (which is just a
> continuation of the previous search) makes sure that the search
> returns a single result, i.e., that the key specification is not
> ambiguous relative to the DB's contents.
> >   Here, packets up to
> > the next PKT_PUBLIC_KEY will be skipped and subkeys are not registered
> > to the hash table.  Next time keyring_search will be called, the call
> > to lookup_offset_hash_table will fail (as the subkey is not
> > registered) and returns -1.
> It sounds like the bug is in the keyring code and this patch simply
> uncovered it.  (I did a quick test and I don't think the problem
> occurs when using a keybox.)

The problem is straightforward to understand, I think.

When we look for a key on the keyring, we iterate over each of the
keyblocks starting with the keyblock following the last result.  For
each keyblock, we iterate over the public key and any subkeys.  As we
iterate over each key, we first insert it into the cache and then
check if the key matches.  If so, we are done.

In pseudo code:

  for (i = last_result + 1; i < num_records; i ++)
    keyblock = get_keyblock (i)
    for (j = 1; j < len(keyblock); j ++)
      key = keyblock[j]
      update_cache (key)
      if (compare (key, search_terms))
        return ok
  cache_filled = true
  return ENOFOUND

When we look for the next match, we start with the following keyblock.
The result is that any subkeys following the key that matched are not
added to the cache (in other words, when a keyblock matches, the inner
loop did not necessarily complete and the subsequent search doesn't
resume it).

7546e81 includes a straightforward fix: only indicate the cache as
complete if we started the scan from the beginning of the keyring and
really didn't find anything.

Thanks for the helpful bug report!  make check still works and your
example works for me as well.


:) Neal

More information about the Gnupg-devel mailing list