1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-23 15:07:03 +01:00

gpg: Fix regression due to recent commit 6500f33

* g10/keydb.c (kid_list_s): Keep a state in the table.
(kid_not_found_table): Rename to kid_found_table.
(n_kid_not_found_table): Rename to kid_found_table_count.
(kid_not_found_p): Return found state.
(kid_not_found_insert): Add arg found.
(keydb_search): Store found state in the table.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-06-22 15:15:39 +02:00
parent 444e9232aa
commit e0873a3372
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -80,17 +80,17 @@ typedef struct kid_list_s
{ {
struct kid_list_s *next; struct kid_list_s *next;
u32 kid[2]; u32 kid[2];
int state; /* True if found. */
} *kid_list_t; } *kid_list_t;
/* To avoid looking up a key by keyid where we know that it does not /* To avoid looking up a key by keyid where we know that it does not
yet exist, we keep a table of keyids where a search resulted in yet exist, we keep a table of keyids with search results. This
not-found. This improves the --list-sigs and --check-sigs commands improves the --list-sigs and --check-sigs commands substantively.
substantively. To avoid extra complexity we clear the entire table To avoid extra complexity we clear the entire table on any insert
on any inert or update operation. The array is indexed by the or update operation. The array is indexed by the LSB of the keyid.
LSByte of the keyid. N_KID_NOT_FOUND_TABLE is the nu,ber of keys KID_FOUND_TABLE_COUNT gives the number of keys in the table. */
in the table. */ static kid_list_t kid_found_table[256];
static kid_list_t kid_not_found_table[256]; static unsigned int kid_found_table_count;
static unsigned int n_kid_not_found_table;
/* This is a simple cache used to return the last result of a /* This is a simple cache used to return the last result of a
@ -118,34 +118,54 @@ static int lock_all (KEYDB_HANDLE hd);
static void unlock_all (KEYDB_HANDLE hd); static void unlock_all (KEYDB_HANDLE hd);
/* Return true if the keyid KID is in the table of keyids whcih were /* Checkwhether the keyid KID is in the table of found or not found
not found in a previous searches. */ keyids.
Returns:
0 - Keyid not in table
1 - Keyid in table because not found in a previous search
2 - Keyid in table because found in a previous search
*/
static int static int
kid_not_found_p (u32 *kid) kid_not_found_p (u32 *kid)
{ {
kid_list_t k; kid_list_t k;
for (k = kid_not_found_table[kid[0] % 256]; k; k = k->next) for (k = kid_found_table[kid[0] % 256]; k; k = k->next)
if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) if (k->kid[0] == kid[0] && k->kid[1] == kid[1])
return 1; {
if (DBG_CACHE)
log_debug ("keydb: kid_not_found_p (%08lx%08lx) => %s\n",
(ulong)kid[0], (ulong)kid[1],
k->state? "false (found)": "true");
return k->state? 2 : 1;
}
if (DBG_CACHE)
log_debug ("keydb: kid_not_found_p (%08lx%08lx) => false\n",
(ulong)kid[0], (ulong)kid[1]);
return 0; return 0;
} }
/* Put the keyid KID into the table of keyids whcih were not found in /* Put the keyid KID into the table of keyids with their find states of
previous searches. Note that there is no check whether the keyid previous searches. Note that there is no check whether the keyid
is already in the table, thus kid_not_found_p() should be used prior. */ is already in the table, thus kid_not_found_p() should be used prior. */
static void static void
kid_not_found_insert (u32 *kid) kid_not_found_insert (u32 *kid, int found)
{ {
kid_list_t k; kid_list_t k;
if (DBG_CACHE)
log_debug ("keydb: kid_not_found_insert (%08lx%08lx, %d)\n",
(ulong)kid[0], (ulong)kid[1], found);
k = xmalloc (sizeof *k); k = xmalloc (sizeof *k);
k->kid[0] = kid[0]; k->kid[0] = kid[0];
k->kid[1] = kid[1]; k->kid[1] = kid[1];
k->next = kid_not_found_table[kid[0]%256]; k->state = found;
kid_not_found_table[kid[0]%256] = k; k->next = kid_found_table[kid[0]%256];
n_kid_not_found_table++; kid_found_table[kid[0]%256] = k;
kid_found_table_count++;
} }
@ -157,19 +177,22 @@ kid_not_found_flush (void)
kid_list_t k, knext; kid_list_t k, knext;
int i; int i;
if (!n_kid_not_found_table) if (DBG_CACHE)
log_debug ("keydb: kid_not_found_flush\n");
if (!kid_found_table_count)
return; return;
for (i=0; i < DIM(kid_not_found_table); i++) for (i=0; i < DIM(kid_found_table); i++)
{ {
for (k = kid_not_found_table[i]; k; k = knext) for (k = kid_found_table[i]; k; k = knext)
{ {
knext = k->next; knext = k->next;
xfree (k); xfree (k);
} }
kid_not_found_table[i] = NULL; kid_found_table[i] = NULL;
} }
n_kid_not_found_table = 0; kid_found_table_count = 0;
} }
@ -605,8 +628,8 @@ keydb_add_resource (const char *url, unsigned int flags)
void void
keydb_dump_stats (void) keydb_dump_stats (void)
{ {
if (n_kid_not_found_table) if (kid_found_table_count)
log_info ("keydb: kid_not_found_table: total: %u\n", n_kid_not_found_table); log_info ("keydb: kid_not_found_table: total: %u\n", kid_found_table_count);
} }
@ -1578,6 +1601,7 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
size_t ndesc, size_t *descindex) size_t ndesc, size_t *descindex)
{ {
gpg_error_t rc; gpg_error_t rc;
int once_found = 0;
if (descindex) if (descindex)
*descindex = 0; /* Make sure it is always set on return. */ *descindex = 0; /* Make sure it is always set on return. */
@ -1592,8 +1616,14 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
dump_search_desc (hd, "keydb_search", desc, ndesc); dump_search_desc (hd, "keydb_search", desc, ndesc);
/* Note that we track the found state in the table to cope with the
case that a initial search found the key and the next search
(without a reset) did not found the key. Without keeping the
found state we would falsely claim that the key has not been
found. Actually this is quite common because we need to check
for ambgious keyids. */
if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID
&& kid_not_found_p (desc[0].u.kid)) && (once_found = kid_not_found_p (desc[0].u.kid)) == 1 )
{ {
if (DBG_CLOCK) if (DBG_CLOCK)
log_clock ("keydb_search leave (not found, cached)"); log_clock ("keydb_search leave (not found, cached)");
@ -1658,10 +1688,11 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
memcpy (keyblock_cache.fpr, desc[0].u.fpr, 20); memcpy (keyblock_cache.fpr, desc[0].u.fpr, 20);
} }
if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND if ((!rc || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
&& ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) && ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID
&& !once_found)
{ {
kid_not_found_insert (desc[0].u.kid); kid_not_found_insert (desc[0].u.kid, !rc);
} }
if (DBG_CLOCK) if (DBG_CLOCK)