fixes for bugs 123479 and 123081 (possibly others). break up arena usage in hash table entries for the temp store and cert cache.

git-svn-id: svn://10.0.0.236/trunk@113727 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ian.mcgreer%sun.com
2002-02-05 23:55:43 +00:00
parent dfc55d137a
commit 528032c847
2 changed files with 68 additions and 19 deletions

View File

@@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: pkistore.c,v $ $Revision: 1.5 $ $Date: 2002-01-31 17:08:32 $ $Name: not supported by cvs2svn $";
static const char CVS_ID[] = "@(#) $RCSfile: pkistore.c,v $ $Revision: 1.6 $ $Date: 2002-02-05 23:55:42 $ $Name: not supported by cvs2svn $";
#endif /* DEBUG */
#ifndef PKIM_H
@@ -182,7 +182,7 @@ add_certificate_entry
{
PRStatus nssrv;
certificate_hash_entry *entry;
entry = nss_ZNEW(store->arena, certificate_hash_entry);
entry = nss_ZNEW(cert->object.arena, certificate_hash_entry);
if (!entry) {
return PR_FAILURE;
}
@@ -209,7 +209,7 @@ add_subject_entry
nssrv = nssList_AddUnique(subjectList, cert);
} else {
/* Create a new subject list for the subject */
subjectList = nssList_Create(store->arena, PR_FALSE);
subjectList = nssList_Create(NULL, PR_FALSE);
if (!subjectList) {
return PR_FAILURE;
}
@@ -290,9 +290,17 @@ remove_subject_entry
if (subjectList) {
/* Remove the cert from the subject hash */
nssList_Remove(subjectList, cert);
nssHash_Remove(store->subject, &cert->subject);
if (nssList_Count(subjectList) == 0) {
nssHash_Remove(store->subject, &cert->subject);
nssList_Destroy(subjectList);
} else {
/* The cert being released may have keyed the subject entry.
* Since there are still subject certs around, get another and
* rekey the entry just in case.
*/
NSSCertificate *subjectCert;
(void)nssList_GetArray(subjectList, (void **)&subjectCert, 1);
nssHash_Add(store->subject, &subjectCert->subject, subjectList);
}
}
}

View File

@@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: tdcache.c,v $ $Revision: 1.23 $ $Date: 2002-01-31 17:08:32 $ $Name: not supported by cvs2svn $";
static const char CVS_ID[] = "@(#) $RCSfile: tdcache.c,v $ $Revision: 1.24 $ $Date: 2002-02-05 23:55:43 $ $Name: not supported by cvs2svn $";
#endif /* DEBUG */
#ifndef PKIM_H
@@ -123,18 +123,22 @@ struct cache_entry_str
} entry;
PRUint32 hits;
PRTime lastHit;
NSSArena *arena;
};
typedef struct cache_entry_str cache_entry;
static cache_entry *
new_cache_entry(NSSArena *arena, void *value)
new_cache_entry(NSSArena *arena, void *value, PRBool ownArena)
{
cache_entry *ce = nss_ZNEW(arena, cache_entry);
if (ce) {
ce->entry.value = value;
ce->hits = 1;
ce->lastHit = PR_Now();
if (ownArena) {
ce->arena = arena;
}
}
return ce;
}
@@ -220,6 +224,13 @@ loser:
return PR_FAILURE;
}
/* The entries of the hashtable are currently dependent on the certificate(s)
* that produced them. That is, the entries will be freed when the cert is
* released from the cache. If there are certs in the cache at any time,
* including shutdown, the hash table entries will hold memory. In order for
* clean shutdown, it is necessary for there to be no certs in the cache.
*/
NSS_IMPLEMENT PRStatus
nssTrustDomain_DestroyCache
(
@@ -262,18 +273,21 @@ remove_subject_entry
(
nssTDCertificateCache *cache,
NSSCertificate *cert,
nssList **subjectList
nssList **subjectList,
NSSArena **arena
)
{
PRStatus nssrv;
cache_entry *ce;
*subjectList = NULL;
*arena = NULL;
/* Get the subject list for the cert's subject */
ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject);
if (ce) {
/* Remove the cert from the subject hash */
nssList_Remove(ce->entry.list, cert);
*subjectList = ce->entry.list;
*arena = ce->arena;
nssrv = PR_SUCCESS;
#ifdef DEBUG_CACHE
log_cert_ref("removed cert", cert);
@@ -333,6 +347,10 @@ remove_email_entry
*/
(void)nssList_Destroy(subjects);
nssHash_Remove(cache->email, cert->email);
/* there are no entries left for this address, free space
* used for email entries
*/
nssArena_Destroy(ce->arena);
#ifdef DEBUG_CACHE
PR_LOG(s_log, PR_LOG_DEBUG, ("removed email %s", cert->email));
#endif
@@ -353,6 +371,7 @@ nssTrustDomain_RemoveCertFromCache
nssList *subjectList;
PRStatus nssrv;
cache_entry *ce;
NSSArena *arena;
#ifdef DEBUG_CACHE
log_cert_ref("attempt to remove cert", cert);
#endif
@@ -372,7 +391,7 @@ nssTrustDomain_RemoveCertFromCache
if (nssrv != PR_SUCCESS) {
goto loser;
}
nssrv = remove_subject_entry(td->cache, cert, &subjectList);
nssrv = remove_subject_entry(td->cache, cert, &subjectList, &arena);
if (nssrv != PR_SUCCESS) {
goto loser;
}
@@ -388,6 +407,12 @@ nssTrustDomain_RemoveCertFromCache
#endif
(void)nssList_Destroy(subjectList);
nssHash_Remove(td->cache->subject, &cert->subject);
/* there are no entries left for this subject, free the space used
* for both the nickname and subject entries
*/
if (arena) {
nssArena_Destroy(arena);
}
}
PZ_Unlock(td->cache->lock);
NSSCertificate_Destroy(cert); /* release the reference */
@@ -463,7 +488,7 @@ add_issuer_and_serial_entry
)
{
cache_entry *ce;
ce = new_cache_entry(arena, (void *)cert);
ce = new_cache_entry(arena, (void *)cert, PR_FALSE);
#ifdef DEBUG_CACHE
log_cert_ref("added to issuer/sn", cert);
#endif
@@ -499,7 +524,7 @@ add_subject_entry
if (!list) {
return PR_FAILURE;
}
ce = new_cache_entry(arena, (void *)list);
ce = new_cache_entry(arena, (void *)list, PR_TRUE);
if (!ce) {
return PR_FAILURE;
}
@@ -546,7 +571,7 @@ add_nickname_entry
return PR_FAILURE;
} else {
NSSUTF8 *nickname;
ce = new_cache_entry(arena, subjectList);
ce = new_cache_entry(arena, subjectList, PR_FALSE);
if (!ce) {
return PR_FAILURE;
}
@@ -565,7 +590,6 @@ add_nickname_entry
static PRStatus
add_email_entry
(
NSSArena *arena,
nssTDCertificateCache *cache,
NSSCertificate *cert,
nssList *subjectList
@@ -586,27 +610,37 @@ add_email_entry
#endif
} else {
NSSASCII7 *email;
NSSArena *arena;
arena = nssArena_Create();
if (!arena) {
return PR_FAILURE;
}
/* Create a new list of subject lists, add this subject */
subjects = nssList_Create(arena, PR_TRUE);
if (!subjects) {
nssArena_Destroy(arena);
return PR_FAILURE;
}
/* Add the new subject to the list */
nssrv = nssList_AddUnique(subjects, subjectList);
if (nssrv != PR_SUCCESS) {
nssArena_Destroy(arena);
return nssrv;
}
/* Add the new entry to the cache */
ce = new_cache_entry(arena, (void *)subjects);
ce = new_cache_entry(arena, (void *)subjects, PR_TRUE);
if (!ce) {
nssArena_Destroy(arena);
return PR_FAILURE;
}
email = nssUTF8_Duplicate(cert->email, arena);
if (!email) {
nssArena_Destroy(arena);
return PR_FAILURE;
}
nssrv = nssHash_Add(cache->email, email, ce);
if (nssrv != PR_SUCCESS) {
nssArena_Destroy(arena);
return nssrv;
}
#ifdef DEBUG_CACHE
@@ -625,11 +659,10 @@ add_cert_to_cache
NSSCertificate *cert
)
{
NSSArena *arena;
NSSArena *arena = NULL;
nssList *subjectList;
PRStatus nssrv;
PRUint32 added = 0;
arena = td->cache->arena;
PZ_Lock(td->cache->lock);
/* If it exists in the issuer/serial hash, it's already in all */
if (nssHash_Exists(td->cache->issuerAndSN, cert)) {
@@ -643,12 +676,17 @@ add_cert_to_cache
nss_SetError(NSS_ERROR_CERTIFICATE_IN_CACHE);
return PR_FAILURE;
}
/* create a new cache entry for this cert */
nssrv = add_issuer_and_serial_entry(arena, td->cache, cert);
/* create a new cache entry for this cert within the cert's arena*/
nssrv = add_issuer_and_serial_entry(cert->object.arena, td->cache, cert);
if (nssrv != PR_SUCCESS) {
goto loser;
}
added++;
/* create an arena for the nickname and subject entries */
arena = nssArena_Create();
if (!arena) {
goto loser;
}
/* create a new subject list for this cert, or add to existing */
nssrv = add_subject_entry(arena, td->cache, cert, &subjectList);
if (nssrv != PR_SUCCESS) {
@@ -667,7 +705,7 @@ add_cert_to_cache
added++;
}
if (cert->email) {
nssrv = add_email_entry(arena, td->cache, cert, subjectList);
nssrv = add_email_entry(td->cache, cert, subjectList);
if (nssrv != PR_SUCCESS) {
goto loser;
}
@@ -695,7 +733,7 @@ loser:
(void)remove_issuer_and_serial_entry(td->cache, cert);
}
if (added >= 2) {
(void)remove_subject_entry(td->cache, cert, &subjectList);
(void)remove_subject_entry(td->cache, cert, &subjectList, &arena);
}
if (added == 3 || added == 5) {
(void)remove_nickname_entry(td->cache, cert, subjectList);
@@ -703,6 +741,9 @@ loser:
if (added >= 4) {
(void)remove_email_entry(td->cache, cert, subjectList);
}
if (arena) {
nssArena_Destroy(arena);
}
PZ_Unlock(td->cache->lock);
return PR_FAILURE;
}