summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexei.volkov.bugs%sun.com <devnull@localhost>2008-03-26 18:49:05 +0000
committeralexei.volkov.bugs%sun.com <devnull@localhost>2008-03-26 18:49:05 +0000
commit97412bfb962279506fd1b7720311395b6d76424a (patch)
tree31649733bc2b8c28c36bd4e5e0451e727cc41fe5
parent9376585d5529b650b8210d1cbcc88c3264be521e (diff)
downloadnss-hg-97412bfb962279506fd1b7720311395b6d76424a.tar.gz
397832 - libpkix leaks memory if a macro calls a function that returns an error. Object leak test. r=nelson
-rw-r--r--security/coreconf/config.mk7
-rw-r--r--security/nss/lib/certhigh/certvfypkix.c149
-rwxr-xr-xsecurity/nss/lib/libpkix/include/pkix.h4
-rwxr-xr-xsecurity/nss/lib/libpkix/include/pkix_errorstrings.h2
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c8
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix/top/pkix_lifecycle.c103
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix/top/pkix_validate.c2
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix/util/pkix_tools.c130
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix/util/pkix_tools.h89
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c38
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c2
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c26
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c49
-rwxr-xr-xsecurity/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c28
-rw-r--r--security/nss/lib/nss/nssinit.c2
-rwxr-xr-xsecurity/nss/tests/libpkix/libpkix.sh112
-rw-r--r--security/nss/tests/memleak/memleak.sh24
17 files changed, 645 insertions, 130 deletions
diff --git a/security/coreconf/config.mk b/security/coreconf/config.mk
index e679f5200..962bff330 100644
--- a/security/coreconf/config.mk
+++ b/security/coreconf/config.mk
@@ -190,6 +190,13 @@ ifdef BUILD_LIBPKIX_TESTS
DEFINES += -DBUILD_LIBPKIX_TESTS
endif
+# Avoid building object leak test code for optimized library
+ifndef BUILD_OPT
+ifdef PKIX_OBJECT_LEAK_TEST
+DEFINES += -DPKIX_OBJECT_LEAK_TEST
+endif
+endif
+
# This allows all library and tools code to use the util function
# implementations directly from libnssutil3, rather than the wrappers
# in libnss3 which are present for binary compatibility only
diff --git a/security/nss/lib/certhigh/certvfypkix.c b/security/nss/lib/certhigh/certvfypkix.c
index 87b01fb95..44adef837 100644
--- a/security/nss/lib/certhigh/certvfypkix.c
+++ b/security/nss/lib/certhigh/certvfypkix.c
@@ -75,6 +75,18 @@ cert_PrintCertChain(PKIX_List *pkixCertChain, void *plContext);
#endif /* DEBUG */
+#ifdef PKIX_OBJECT_LEAK_TEST
+
+extern PKIX_UInt32
+pkix_pl_lifecycle_ObjectLeakCheck(int *);
+
+extern SECStatus
+pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
+
+PRInt32 parallelFnInvocationCount;
+
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
static PRBool usePKIXValidationEngine = PR_FALSE;
@@ -312,10 +324,12 @@ cert_NssCertificateUsageToPkixKUAndEKU(
PKIX_DECREF(ekuOid);
}
- cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext);
+ PKIX_CHECK(
+ cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
+ PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
*ppkixEKUList = ekuOidsList;
- PKIX_INCREF(ekuOidsList);
+ ekuOidsList = NULL;
cleanup:
@@ -362,11 +376,11 @@ cert_ProcessingParamsSetKuAndEku(
PRUint32 requiredKeyUsages,
void *plContext)
{
- PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext*)plContext;
PKIX_List *extKeyUsage = NULL;
- PKIX_UInt32 keyUsage = 0;
PKIX_CertSelector *certSelector = NULL;
PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext*)plContext;
+ PKIX_UInt32 keyUsage = 0;
PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKuAndEku");
PKIX_NULLCHECK_TWO(procParams, nssContext);
@@ -848,12 +862,6 @@ cert_PkixErrorToNssCode(
PKIX_RETURN(CERTVFYPKIX);
}
-
-extern void
-cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert,
- unsigned long errorCode, unsigned int depth,
- void *arg);
-
/*
* FUNCTION: cert_GetLogFromVerifyNode
* DESCRIPTION:
@@ -881,10 +889,8 @@ cert_GetLogFromVerifyNode(
PKIX_VerifyNode *node,
void *plContext)
{
- PKIX_UInt32 length = 0;
PKIX_List *children = NULL;
PKIX_VerifyNode *childNode = NULL;
- CERTCertificate *cert = NULL;
PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
@@ -900,11 +906,9 @@ cert_GetLogFromVerifyNode(
#endif
if (log != NULL) {
SECErrorCodes nssErrorCode = 0;
+ CERTCertificate *cert = NULL;
- PKIX_CHECK(
- PKIX_PL_Cert_GetCERTCertificate(node->verifyCert, &cert,
- plContext),
- PKIX_CERTGETCERTCERTIFICATEFAILED);
+ cert = node->verifyCert->nssCert;
PKIX_CHECK(
cert_PkixErrorToNssCode(node->error, &nssErrorCode,
@@ -916,7 +920,8 @@ cert_GetLogFromVerifyNode(
}
PKIX_RETURN(CERTVFYPKIX);
} else {
- PRUint32 i = 0;
+ PRUint32 i = 0;
+ PKIX_UInt32 length = 0;
PKIX_CHECK(
PKIX_List_GetLength(children, &length, plContext),
@@ -938,9 +943,6 @@ cert_GetLogFromVerifyNode(
}
cleanup:
- if (cert) {
- CERT_DestroyCertificate(cert);
- }
PKIX_DECREF(childNode);
PKIX_RETURN(CERTVFYPKIX);
@@ -1163,6 +1165,44 @@ cert_VerifyCertChainPkix(
CERTCertList *validChain = NULL;
#endif /* DEBUG */
+#ifdef PKIX_OBJECT_LEAK_TEST
+ int leakedObjNum = 0;
+ int memLeakLoopCount = 0;
+ int objCountTable[PKIX_NUMTYPES];
+ int fnInvLocalCount = 0;
+
+ fnStackNameArr[0] = "cert_VerifyCertChainPkix";
+ fnStackInvCountArr[0] = 0;
+ PKIX_Boolean abortOnLeak =
+ (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
+ PKIX_FALSE : PKIX_TRUE;
+ runningLeakTest = PKIX_TRUE;
+
+ /* Prevent multi-threaded run of object leak test */
+ fnInvLocalCount = PR_AtomicIncrement(&parallelFnInvocationCount);
+ PORT_Assert(fnInvLocalCount == 1);
+
+do {
+ rv = SECFailure;
+ plContext = NULL;
+ procParams = NULL;
+ result = NULL;
+ verifyNode = NULL;
+ error = NULL;
+#ifdef DEBUG_volkov
+ trustedRoot = NULL;
+ validChain = NULL;
+#endif /* DEBUG */
+ errorGenerated = PKIX_FALSE;
+ stackPosition = 0;
+
+ if (leakedObjNum) {
+ pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
+ }
+
+ PR_LOG(pkixLog, 1, ("Memory leak test: Loop %d\n", memLeakLoopCount));
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
error =
cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
PR_FALSE/*use arena*/,
@@ -1231,6 +1271,21 @@ cleanup:
if (plContext) {
PKIX_PL_NssContext_Destroy(plContext);
}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ leakedObjNum =
+ pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
+
+ if (abortOnLeak) {
+ PORT_Assert(leakedObjNum == 0);
+ }
+
+} while (errorGenerated);
+
+ runningLeakTest = PKIX_FALSE;
+ PR_AtomicDecrement(&parallelFnInvocationCount);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
return rv;
}
@@ -1954,6 +2009,46 @@ SECStatus CERT_PKIXVerifyCert(
void *plContext = NULL;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ int leakedObjNum = 0;
+ int memLeakLoopCount = 0;
+ int objCountTable[PKIX_NUMTYPES];
+ int fnInvLocalCount = 0;
+ fnStackNameArr[0] = "CERT_PKIXVerifyCert";
+ fnStackInvCountArr[0] = 0;
+ PKIX_Boolean abortOnLeak =
+ PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") ?
+ PKIX_FALSE : PKIX_TRUE;
+ runningLeakTest = PKIX_TRUE;
+
+ /* Prevent multi-threaded run of object leak test */
+ fnInvLocalCount = PR_AtomicIncrement(&parallelFnInvocationCount);
+ PORT_Assert(fnInvLocalCount == 1);
+
+do {
+ r = SECFailure;
+ error = NULL;
+ procParams = NULL;
+ buildResult = NULL;
+ nbioContext = NULL; /* for non-blocking IO */
+ buildState = NULL; /* for non-blocking IO */
+ certSelector = NULL;
+ certStores = NULL;
+ valResult = NULL;
+ trustAnchor = NULL;
+ trustAnchorCert = NULL;
+ oparam = NULL;
+ i=0;
+ errorGenerated = PKIX_FALSE;
+ stackPosition = 0;
+
+ if (leakedObjNum) {
+ pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
+ }
+
+ PR_LOG(pkixLog, 1, ("Memory leak test: Loop %d\n", memLeakLoopCount));
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
error = PKIX_PL_NssContext_Create(
0, PR_FALSE /*use arena*/, wincx, &plContext);
if (error != NULL) { /* need pkix->nss error map */
@@ -2090,6 +2185,20 @@ cleanup:
PKIX_PL_NssContext_Destroy(plContext);
+#ifdef PKIX_OBJECT_LEAK_TEST
+ leakedObjNum =
+ pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
+
+ if (abortOnLeak) {
+ PORT_Assert(leakedObjNum == 0);
+ }
+
+} while (errorGenerated);
+
+ runningLeakTest = PKIX_FALSE;
+ PR_AtomicDecrement(&parallelFnInvocationCount);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
return r;
}
diff --git a/security/nss/lib/libpkix/include/pkix.h b/security/nss/lib/libpkix/include/pkix.h
index bae5daf70..0be4c50e7 100755
--- a/security/nss/lib/libpkix/include/pkix.h
+++ b/security/nss/lib/libpkix/include/pkix.h
@@ -116,9 +116,6 @@ extern "C" {
* "platformInitNeeded"
* Boolean indicating whether the platform layer initialization code
* has previously been run, or should be called from this function.
- * "useArenas"
- * Boolean indicating whether allocation is to be done using arenas or
- * individual allocation (malloc).
* "desiredMajorVersion"
* The major version of the libpkix API the application wishes to use.
* "minDesiredMinorVersion"
@@ -142,7 +139,6 @@ extern "C" {
PKIX_Error *
PKIX_Initialize(
PKIX_Boolean platformInitNeeded,
- PKIX_Boolean useArenas,
PKIX_UInt32 desiredMajorVersion,
PKIX_UInt32 minDesiredMinorVersion,
PKIX_UInt32 maxDesiredMinorVersion,
diff --git a/security/nss/lib/libpkix/include/pkix_errorstrings.h b/security/nss/lib/libpkix/include/pkix_errorstrings.h
index e62dc6ea7..c5de81baf 100755
--- a/security/nss/lib/libpkix/include/pkix_errorstrings.h
+++ b/security/nss/lib/libpkix/include/pkix_errorstrings.h
@@ -681,6 +681,7 @@ PKIX_ERRORENTRY(LOOPOFERRORCAUSEDETECTED,Loop of error causes detected,0),
PKIX_ERRORENTRY(MAJORVERSIONSDONTMATCH,Major versions do not match,SEC_ERROR_INVALID_ARGS),
PKIX_ERRORENTRY(MALLOCFAILED,PKIX_PL_Malloc failed,0),
PKIX_ERRORENTRY(MEMCPYFAILED,PKIX_PL_Memcpy failed,0),
+PKIX_ERRORENTRY(MEMLEAKGENERATEDERROR,Error generated for memory leak testing,SEC_ERROR_NO_MEMORY),
PKIX_ERRORENTRY(MINORVERSIONNOTBETWEENDESIREDMINANDMAX,Minor version does not fall between desired minimum and maximum,SEC_ERROR_INVALID_ARGS),
PKIX_ERRORENTRY(MISSINGDSAPARAMETERS,Missing DSA parameters in Trusted Cert,SEC_ERROR_INVALID_KEY),
PKIX_ERRORENTRY(MONITORLOCKCREATEFAILED,PKIX_PL_MonitorLock_Create failed,0),
@@ -700,6 +701,7 @@ PKIX_ERRORENTRY(NORESPONSEDATAINHTTPRESPONSE,No responseData in Http Response,SE
PKIX_ERRORENTRY(NOTARGETCERTSUPPLIED,No target cert supplied,SEC_ERROR_INVALID_ARGS),
PKIX_ERRORENTRY(NOTDERPACKAGE,Not a DER package,0),
PKIX_ERRORENTRY(NOTENOUGHNAMECOMPONENTSINGENERALNAME,Not enough name components in GeneralName,0),
+PKIX_ERRORENTRY(NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED,Failed to convert nss certificate usage to pkix ku and eku data structures,0),
PKIX_ERRORENTRY(NSSCONTEXTCREATEFAILED,PKIX_PL_NssContext_Create failed,0),
PKIX_ERRORENTRY(NSSCONTEXTDESTROYFAILED,PKIX_PL_NssContext_Destroy failed,0),
PKIX_ERRORENTRY(NSSCONTEXTGETCHECKALLUSAGESFAILED, pkix_pl_NssContext_GetCheckAllUsages failed,0),
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
index d968b0e5a..13ebcf752 100644
--- a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
@@ -204,10 +204,10 @@ pkix_OcspChecker_Check(
}
goto cleanup;
}
-
PKIX_INCREF(cert);
+ PKIX_DECREF(checker->cert);
checker->cert = cert;
-
+
/* create request */
PKIX_CHECK(pkix_pl_OcspRequest_Create
(cert,
@@ -301,7 +301,9 @@ cleanup:
PKIX_DECREF(cid);
PKIX_DECREF(request);
- PKIX_DECREF(checker->response);
+ if (checker) {
+ PKIX_DECREF(checker->response);
+ }
PKIX_RETURN(OCSPCHECKER);
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
index 79c7754b4..3d377cce0 100755
--- a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
+++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
@@ -43,8 +43,7 @@
#include "pkix_lifecycle.h"
-static PKIX_Boolean pkixIsInitialized = PKIX_FALSE;
-static PKIX_Boolean pkixInitInProgress = PKIX_FALSE;
+static PKIX_Boolean pkixIsInitialized;
/* Lock used by Logger - is reentrant by the same thread */
extern PKIX_PL_MonitorLock *pkixLoggerLock;
@@ -82,7 +81,6 @@ extern PKIX_List *pkixLoggersDebugTrace;
PKIX_Error *
PKIX_Initialize(
PKIX_Boolean platformInitNeeded,
- PKIX_Boolean useArenas,
PKIX_UInt32 desiredMajorVersion,
PKIX_UInt32 minDesiredMinorVersion,
PKIX_UInt32 maxDesiredMinorVersion,
@@ -95,18 +93,6 @@ PKIX_Initialize(
PKIX_NULLCHECK_ONE(pPlContext);
/*
- * This function can only be called once, except for a special-situation
- * recursive call. If platformInitNeeded is TRUE, this function
- * initializes the platform support layer, such as NSS. But that
- * layer expects to initialize us! So we return immediately if we
- * recognize that we are in this nested call situation.
- */
-
- if (pkixInitInProgress && (platformInitNeeded == PKIX_FALSE)) {
- goto cleanup;
- }
-
- /*
* If we are called a second time other than in the situation handled
* above, we return a positive status.
*/
@@ -115,10 +101,8 @@ PKIX_Initialize(
PKIX_RETURN(LIFECYCLE);
}
- pkixInitInProgress = PKIX_TRUE;
-
PKIX_CHECK(PKIX_PL_Initialize
- (platformInitNeeded, useArenas, &plContext),
+ (platformInitNeeded, PKIX_FALSE, &plContext),
PKIX_INITIALIZEFAILED);
*pPlContext = plContext;
@@ -134,43 +118,62 @@ PKIX_Initialize(
*pActualMinorVersion = PKIX_MINOR_VERSION;
- pkixInitInProgress = PKIX_FALSE;
- pkixIsInitialized = PKIX_TRUE;
-
- /* Create Cache Tables */
+ /* Create Cache Tables
+ * Do not initialize hash tables for object leak test */
+#if !defined(PKIX_OBJECT_LEAK_TEST)
PKIX_CHECK(PKIX_PL_HashTable_Create
- (32, 0, &cachedCertSigTable, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (32, 0, &cachedCertSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (32, 0, &cachedCrlSigTable, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (32, 0, &cachedCrlSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (32, 10, &cachedCertChainTable, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (32, 10, &cachedCertChainTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (32, 10, &cachedCertTable, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (32, 10, &cachedCertTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (32, 10, &cachedCrlEntryTable, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (32, 10, &cachedCrlEntryTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (5, 5, &aiaConnectionCache, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (5, 5, &aiaConnectionCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
PKIX_CHECK(PKIX_PL_HashTable_Create
- (5, 5, &httpSocketCache, plContext),
- PKIX_HASHTABLECREATEFAILED);
-
+ (5, 5, &httpSocketCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
if (pkixLoggerLock == NULL) {
- PKIX_CHECK(PKIX_PL_MonitorLock_Create
- (&pkixLoggerLock, plContext),
- PKIX_MONITORLOCKCREATEFAILED);
+ PKIX_CHECK(PKIX_PL_MonitorLock_Create
+ (&pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKCREATEFAILED);
+ }
+#else
+ fnInvTable = PL_NewHashTable(0, pkix_ErrorGen_Hash,
+ PL_CompareValues,
+ PL_CompareValues, NULL, NULL);
+ if (!fnInvTable) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackNameArr = PORT_ZNewArray(char*, MAX_STACK_DEPTH);
+ if (!fnStackNameArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackInvCountArr = PORT_ZNewArray(PKIX_UInt32, MAX_STACK_DEPTH);
+ if (!fnStackInvCountArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
}
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ pkixIsInitialized = PKIX_TRUE;
cleanup:
@@ -194,6 +197,8 @@ PKIX_Shutdown(void *plContext)
PKIX_RETURN(LIFECYCLE);
}
+ pkixIsInitialized = PKIX_FALSE;
+
if (pkixLoggers) {
savedPkixLoggers = pkixLoggers;
savedPkixLoggersErrors = pkixLoggersErrors;
@@ -225,7 +230,11 @@ PKIX_Shutdown(void *plContext)
PKIX_CHECK(PKIX_PL_Shutdown(plContext),
PKIX_SHUTDOWNFAILED);
- pkixIsInitialized = PKIX_FALSE;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Free(fnStackInvCountArr);
+ PORT_Free(fnStackNameArr);
+ PL_HashTableDestroy(fnInvTable);
+#endif
cleanup:
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.c b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
index 24a531fa5..5da90e350 100755
--- a/security/nss/lib/libpkix/pkix/top/pkix_validate.c
+++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
@@ -1030,7 +1030,7 @@ pkix_CheckChain(
*pNBIOContext = NULL;
cleanup:
- if (PKIX_ERROR_RECEIVED) {
+ if (PKIX_ERROR_RECEIVED && cert) {
pkixErrorReceived = PKIX_TRUE;
pkixErrorCode = pkixErrorResult->errCode;
checkCertError = pkixErrorResult;
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
index 673af8c60..f72d252b9 100755
--- a/security/nss/lib/libpkix/pkix/util/pkix_tools.c
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
@@ -65,8 +65,49 @@ extern int pkix_cRemoveCount;
extern int pkix_ceAddCount;
extern int pkix_ceLookupCount;
+#ifdef PKIX_OBJECT_LEAK_TEST
+/* Following variables are used for object leak test */
+char *nonNullValue = "Non Empty Value";
+PKIX_Boolean noErrorState = PKIX_TRUE;
+PKIX_Boolean runningLeakTest;
+PKIX_Boolean errorGenerated;
+PKIX_UInt32 stackPosition;
+PKIX_UInt32 *fnStackInvCountArr;
+char **fnStackNameArr;
+PLHashTable *fnInvTable;
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
/* --Private-Functions-------------------------------------------- */
+#ifdef PKIX_OBJECT_LEAK_TEST
+/*
+ * FUNCTION: pkix_ErrorGen_Hash
+ * DESCRIPTION:
+ *
+ * Hash function to be used in object leak test hash table.
+ *
+ */
+PLHashNumber PR_CALLBACK
+pkix_ErrorGen_Hash (const void *key)
+{
+ char *str = NULL;
+ PLHashNumber rv = (*(PRUint8*)key) << 5;
+ PRUint32 i, counter = 0;
+ PRUint8 *rvc = (PRUint8 *)&rv;
+
+ while ((str = fnStackNameArr[counter++]) != NULL) {
+ PRUint32 len = strlen(str);
+ for( i = 0; i < len; i++ ) {
+ rvc[ i % sizeof(rv) ] ^= *str;
+ str++;
+ }
+ }
+
+ return rv;
+}
+
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
/*
* FUNCTION: pkix_IsCertSelfIssued
* DESCRIPTION:
@@ -175,9 +216,21 @@ pkix_Throw(
*pError = NULL;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_TRUE;
+ if (pkixLog) {
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
+ funcName, PKIX_ErrorText[errorCode],
+ (cause ? PKIX_ErrorText[cause->errCode] : "null")));
+
+ PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
/* if cause has error class of PKIX_FATAL_ERROR, return immediately */
if (cause) {
if (cause->errClass == PKIX_FATAL_ERROR){
+ PKIX_INCREF(cause);
*pError = cause;
goto cleanup;
}
@@ -205,6 +258,17 @@ cleanup:
PKIX_DEBUG_EXIT(ERROR);
pkixErrorClass = 0;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_FALSE;
+
+ if (runningLeakTest && fnStackNameArr) {
+ PR_LOG(pkixLog, 5,
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
+ stackPosition, " ", fnStackNameArr[stackPosition],
+ stackPosition, myFuncName));
+ fnStackNameArr[stackPosition--] = NULL;
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
return (pkixTempResult);
}
@@ -1407,3 +1471,69 @@ cleanup:
PKIX_RETURN(BUILD);
}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+
+/* TEST_START_FN and TEST_START_FN_STACK_POS define at what state
+ * of the stack the object leak testing should begin. The condition
+ * in pkix_CheckForGeneratedError works the following way: do leak
+ * testing if at position TEST_START_FN_STACK_POS in stack array
+ * (fnStackNameArr) we have called function TEST_START_FN.
+ * Note, that stack array get filled only when executing libpkix
+ * functions.
+ * */
+#define TEST_START_FN "PKIX_BuildChain"
+#define TEST_START_FN_STACK_POS 2
+
+PKIX_Error*
+pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errSetFlag,
+ void * plContext)
+{
+ PKIX_Error *genErr = NULL;
+
+ if (fnName) {
+ if (fnStackNameArr[TEST_START_FN_STACK_POS] == NULL ||
+ strcmp(fnStackNameArr[TEST_START_FN_STACK_POS], TEST_START_FN)
+ ) {
+ /* return with out error if not with in boundary */
+ return NULL;
+ }
+ if (!strcmp(fnName, TEST_START_FN)) {
+ *errSetFlag = PKIX_TRUE;
+ noErrorState = PKIX_FALSE;
+ errorGenerated = PKIX_FALSE;
+ }
+ }
+
+ if (noErrorState || errorGenerated) return NULL;
+
+ if (fnName && (
+ !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
+ !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
+ !strcmp(fnName, "pkix_UnlockObject") ||
+ !strcmp(fnName, "pkix_Throw") ||
+ !strcmp(fnName, "pkix_trace_dump_cert") ||
+ !strcmp(fnName, "PKIX_PL_Free"))) {
+ /* do not generate error for this functions */
+ noErrorState = PKIX_TRUE;
+ *errSetFlag = PKIX_TRUE;
+ return NULL;
+ }
+
+ if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
+ return NULL;
+ }
+
+ PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
+ errorGenerated = PKIX_TRUE;
+ noErrorState = PKIX_TRUE;
+ genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
+ errClass, plContext);
+ noErrorState = PKIX_FALSE;
+
+ return genErr;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
index 9a2a352b9..0e224c495 100755
--- a/security/nss/lib/libpkix/pkix/util/pkix_tools.h
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
@@ -143,6 +143,14 @@ extern void PKIX_DoAddError(PKIX_StdVars * stdVars,
PKIX_Error * error,
void * plContext);
+#ifdef PKIX_OBJECT_LEAK_TEST
+extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errorStateSet,
+ void * plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
extern const PKIX_StdVars zeroStdVars;
extern PRLogModuleInfo *pkixLog;
@@ -160,11 +168,63 @@ extern PRLogModuleInfo *pkixLog;
* not reached"), so we just use "{<body>}" to group the statements together.
*/
+#if !defined (PKIX_OBJECT_LEAK_TEST)
+
#define PKIX_STD_VARS(funcName) \
static const char cMyFuncName[] = {funcName}; \
PKIX_StdVars stdVars = zeroStdVars; \
myFuncName = cMyFuncName
+
+#else /* PKIX_OBJECT_LEAK_TEST */
+
+extern char **fnStackNameArr;
+extern PKIX_UInt32 *fnStackInvCountArr;
+extern PKIX_UInt32 stackPosition;
+extern PKIX_Boolean noErrorState;
+extern PKIX_Boolean errorGenerated;
+extern PKIX_Boolean runningLeakTest;
+extern PLHashTable *fnInvTable;
+
+extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key);
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ PKIX_Boolean errorSetFlag = PKIX_FALSE; \
+ myFuncName = cMyFuncName; \
+ if (runningLeakTest) { \
+ if (fnStackNameArr) { \
+ fnStackInvCountArr[stackPosition] += 1; \
+ stackPosition += 1; \
+ fnStackInvCountArr[stackPosition] = 0; \
+ fnStackNameArr[stackPosition] = (char*)myFuncName; \
+ fnStackNameArr[stackPosition + 1] = NULL; \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ } \
+ do { \
+ pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \
+ funcName, &errorSetFlag, \
+ plContext); \
+ if (pkixErrorResult) { \
+ printf("Error in fn: %s\n", myFuncName); \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) { \
+ noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return pkixErrorResult; \
+ } \
+ } while (0); \
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
#ifdef DEBUG
#define _PKIX_DEBUG_TRACE(cond, prefix, level) \
do { \
@@ -235,20 +295,22 @@ extern PRLogModuleInfo *pkixLog;
return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \
pkixErrorClass, plContext);
-#if defined(DEBUG) && !defined(DEBUG_nb95248)
+#ifdef PKIX_OBJECT_LEAK_TEST
#define PKIX_RETURN(type) \
- { \
- PKIX_OBJECT_UNLOCK(lockedObject); \
- if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \
- PKIX_THROW(type, pkixErrorCode); \
- PKIX_DEBUG_EXIT(type); \
- _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE); \
- return NULL; \
- }
+ if (runningLeakTest && fnStackNameArr) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
#else
#define PKIX_RETURN(type) \
return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
-#endif
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
#if defined(DEBUG) && !defined(DEBUG_nb95248)
#define PKIX_RETURN_NO_LOGGER(type) \
@@ -1400,7 +1462,12 @@ struct pkix_ClassTable_EntryStruct {
*/
extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES];
-#define PKIX_MAGIC_HEADER (PKIX_UInt32) 0xBEEFC0DE
+#define MAX_STACK_DEPTH 1000
+
+extern PRLogModuleInfo *pkixLog;
+
+#define PKIX_MAGIC_HEADER (PKIX_UInt32) 0xBEEFC0DE
+#define PKIX_MAGIC_HEADER_DESTROYED (PKIX_UInt32) 0xDEADC0DE
/* see source file for function documentation */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
index 55ecf9a1a..df7eccdd2 100644
--- a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
@@ -1432,7 +1432,7 @@ pkix_pl_Cert_CreateWithNSSCert(
{
PKIX_PL_Cert *cert = NULL;
- PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNSSCert");
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
PKIX_NULLCHECK_TWO(pCert, nssCert);
/* create a PKIX_PL_Cert object */
@@ -1534,25 +1534,26 @@ pkix_pl_Cert_CreateToList(
PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
PKIX_NULLCHECK_TWO(derCertItem, certList);
- PKIX_PL_NSSCALLRV(CERT, nssCert, CERT_DecodeDERCertificate,
- (derCertItem, PR_TRUE, NULL));
+ nssCert = CERT_DecodeDERCertificate(derCertItem, PR_TRUE, NULL);
+ if (!nssCert) {
+ goto cleanup;
+ }
- if (nssCert) {
- PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert
- (nssCert, &cert, plContext),
- PKIX_CERTCREATEWITHNSSCERTFAILED);
-
- /* skip bad certs and append good ones */
- if (!PKIX_ERROR_RECEIVED) {
- PKIX_CHECK(PKIX_List_AppendItem
- (certList, (PKIX_PL_Object *) cert, plContext),
- PKIX_LISTAPPENDITEMFAILED);
- }
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
- PKIX_DECREF(cert);
- }
+ nssCert = NULL;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (certList, (PKIX_PL_Object *) cert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
cleanup:
+ if (nssCert) {
+ CERT_DestroyCertificate(nssCert);
+ }
+
PKIX_DECREF(cert);
PKIX_RETURN(CERT);
}
@@ -2184,9 +2185,10 @@ PKIX_PL_Cert_GetSubjectPublicKey(
*pPublicKey = cert->publicKey;
cleanup:
- PKIX_OBJECT_UNLOCK(lockedObject);
- if (PKIX_ERROR_RECEIVED){
+
+ if (PKIX_ERROR_RECEIVED && pkixPubKey){
PKIX_DECREF(pkixPubKey);
+ cert->publicKey = NULL;
}
PKIX_RETURN(CERT);
}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
index 073e632b6..880726229 100644
--- a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
@@ -145,7 +145,7 @@ PKIX_PL_OcspCertID_Create(
PKIX_PL_OcspCertID **object,
void *plContext)
{
- PKIX_PL_OcspCertID *cid;
+ PKIX_PL_OcspCertID *cid = NULL;
int64 time = 0;
PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_Create");
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
index 4a53f3707..d9fe830ae 100755
--- a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
@@ -226,8 +226,16 @@ PKIX_PL_HashTable_Add(
PKIX_UInt32 bucketSize = 0;
PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Add");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
PKIX_NULLCHECK_THREE(ht, key, value);
+#else
+ PKIX_NULLCHECK_TWO(key, value);
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
/* Insert into primitive hashtable */
PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
@@ -301,7 +309,16 @@ PKIX_PL_HashTable_Remove(
PKIX_PL_EqualsCallback keyComp;
PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Remove");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
PKIX_NULLCHECK_TWO(ht, key);
+#else
+ PKIX_NULLCHECK_ONE(key);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
PKIX_OBJECTHASHCODEFAILED);
@@ -356,7 +373,16 @@ PKIX_PL_HashTable_Lookup(
PKIX_PL_Object *result = NULL;
PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Lookup");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
PKIX_NULLCHECK_THREE(ht, key, pResult);
+#else
+ PKIX_NULLCHECK_TWO(key, pResult);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
PKIX_OBJECTHASHCODEFAILED);
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
index b42845e4e..0773f1fb7 100755
--- a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
@@ -86,8 +86,25 @@ PKIX_Error* PKIX_ALLOC_ERROR(void)
return &pkix_Alloc_Error_Data.error;
}
-static PKIX_UInt32
-pkix_pl_lifecycle_ObjectLeakCheck()
+#ifdef PKIX_OBJECT_LEAK_TEST
+SECStatus
+pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable)
+{
+ int typeCounter = 0;
+
+ for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
+ pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+
+ objCountTable[typeCounter] = entry->objCounter;
+ }
+
+ return SECSuccess;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+PKIX_UInt32
+pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable)
{
int typeCounter = 0;
PKIX_UInt32 numObjects = 0;
@@ -96,10 +113,17 @@ pkix_pl_lifecycle_ObjectLeakCheck()
for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+ PKIX_UInt32 objCountDiff = entry->objCounter;
+
+ if (initObjCountTable) {
+ PKIX_UInt32 initialCount = initObjCountTable[typeCounter];
+ objCountDiff = (entry->objCounter > initialCount) ?
+ entry->objCounter - initialCount : 0;
+ }
- numObjects += entry->objCounter;
+ numObjects += objCountDiff;
- if (!pkixLog || !entry->objCounter) {
+ if (!pkixLog || !objCountDiff) {
continue;
}
className = entry->description;
@@ -111,8 +135,8 @@ pkix_pl_lifecycle_ObjectLeakCheck()
PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of "
"size %d bytes, total = %d bytes\n", className,
- entry->objCounter, entry->typeObjectSize,
- entry->objCounter * entry->typeObjectSize));
+ objCountDiff, entry->typeObjectSize,
+ objCountDiff * entry->typeObjectSize));
}
return numObjects;
@@ -265,15 +289,10 @@ PKIX_PL_Shutdown(void *plContext)
pkix_pl_HttpCertStore_Shutdown(plContext);
- numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck();
-
- /* Turn this code on again after bug 397832 get fixed.
- * if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
- *
- * PORT_Assert(numLeakedObjects == 0);
- *
- * }
- */
+ numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL);
+ if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) {
+ PORT_Assert(numLeakedObjects == 0);
+ }
if (plContext != NULL) {
PKIX_PL_NssContext_Destroy(plContext);
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
index e98901c41..20adac974 100755
--- a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
@@ -140,6 +140,10 @@ pkix_pl_Object_GetHeader(
#endif /* PKIX_USER_OBJECT_TYPE */
}
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
if ((header == NULL)||
(header->magicHeader != PKIX_MAGIC_HEADER)) {
PKIX_ERROR_ALLOC_ERROR();
@@ -181,15 +185,19 @@ pkix_pl_Object_Destroy(
PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
PKIX_NULLCHECK_ONE(object);
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#else
PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#endif /* PKIX_OBJECT_LEAK_TEST */
/* Attempt to delete an object still being used */
if (objectHeader->references != 0) {
PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
}
- objectHeader->magicHeader = 0;
PKIX_DECREF(objectHeader->stringRep);
/* Destroy this object's lock */
@@ -198,9 +206,18 @@ pkix_pl_Object_Destroy(
objectHeader->lock = NULL;
object = NULL;
+ objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
+#endif
+
PKIX_FREE(objectHeader);
cleanup:
+#ifdef PKIX_OBJECT_LEAK_TEST
+fatal:
+#endif
PKIX_RETURN(OBJECT);
}
@@ -589,8 +606,14 @@ PKIX_PL_Object_Alloc(
PORT_Assert(size == ctEntry->typeObjectSize);
/* Allocate space for the object header and the requested size */
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK(PKIX_PL_Calloc
+ (1,
+ ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+#else
PKIX_CHECK(PKIX_PL_Malloc
(((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+#endif /* PKIX_OBJECT_LEAK_TEST */
(void **)&object,
plContext),
PKIX_MALLOCFAILED);
@@ -603,7 +626,6 @@ PKIX_PL_Object_Alloc(
object->hashcode = 0;
object->hashcodeCached = 0;
-
/* Cannot use PKIX_PL_Mutex because it depends on Object */
/* Using NSPR Locks instead */
PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
@@ -841,7 +863,7 @@ PKIX_PL_Object_DecRef(
PKIX_Int32 refCount = 0;
PKIX_PL_Object *objectHeader = NULL;
PKIX_PL_NssContext *context = NULL;
-
+
PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
PKIX_NULLCHECK_ONE(object);
diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c
index 7ca63528a..32eff5529 100644
--- a/security/nss/lib/nss/nssinit.c
+++ b/security/nss/lib/nss/nssinit.c
@@ -573,7 +573,7 @@ loser:
if (SECSuccess == rv) {
pkixError = PKIX_Initialize
- (PKIX_FALSE, PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION,
+ (PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION,
PKIX_MINOR_VERSION, &actualMinorVersion, &plContext);
if (pkixError != NULL) {
diff --git a/security/nss/tests/libpkix/libpkix.sh b/security/nss/tests/libpkix/libpkix.sh
index cfc519d23..7d3b6caab 100755
--- a/security/nss/tests/libpkix/libpkix.sh
+++ b/security/nss/tests/libpkix/libpkix.sh
@@ -83,7 +83,6 @@ libpkix_init()
LIBPKIX_LOG=${HOSTDIR}/libpkix.log #we don't want all the errormessages
# in the output.log, otherwise we can't tell what's a real error
- html_head "LIBPKIX Tests"
}
@@ -104,6 +103,9 @@ libpkix_cleanup()
. common/cleanup.sh
}
+############################## libpkix_UT_main ############################
+# local shell function to run libpkix unit tests
+########################################################################
ParseArgs ()
{
while [ $# -gt 0 ]; do
@@ -119,9 +121,11 @@ ParseArgs ()
done
}
-libpkix_main()
+libpkix_UT_main()
{
+html_head "LIBPKIX Unit Tests"
+
ParseArgs
echo "*******************************************************************************"
@@ -178,10 +182,110 @@ return 1
fi
}
+############################## libpkix_setup_db ############################
+# Sets up directory and db for pkix functional test.
+########################################################################
+libpkix_setup_db()
+{
+ fnCaller=$1
+
+ DB_DIR="${HOSTDIR}/libpkix_functional"
+ CERT_DIR="${QADIR}/libpkix/certs"
+
+ mkdir -p $DB_DIR
+ if [ ! -f ${R_PWFILE} ]; then
+ echo nss > ${R_PWFILE}
+ fi
+ echo "Initializing Cert DB in $FN_DB_DIR"
+ certutil -N -d "${DB_DIR}" -f "${R_PWFILE}" 2>&1
+ RET=$?
+ if [ "$RET" -ne 0 ]; then
+ return $RET
+ fi
+
+ echo "Loading certs into DB at $DB_DIR"
+ output=$TMP/libpkix_setup.tmp
+ while read certName trusts; do
+ certutil -d $DB_DIR -A -n $certName -t $trusts -i $CERT_DIR/$certName.cert > $output 2>&1
+ if [ $? -ne 0 ]; then
+ echo "WARNING: unable to add a certificate($certName) into database"
+ echo "certutil output:"
+ cat $output
+ fi
+ rm -f $output
+ done < $QADIR/libpkix/cert_trust.map
+
+}
+
+############################## libpkix_leak_test ############################
+# Runs pkix object and memory leak test
+########################################################################
+libpkix_leak_test()
+{
+
+ if [ -n "${MEMLEAK_DBG}" ]; then
+ LOGNAME="libpkix_memleak"
+ LOGFILE=${LOGDIR}/${LOGNAME}.log
+ tmpLogFile=$LOGFILE.tmp
+
+ html_head "Memory leak checking - libpkix"
+ else
+ tmpLogFile=$DB_DIR/libpkix_memoryleak.log
+
+ html_head "LIBPKIX Object Leak Tests"
+ fi
+ while read status leafCert explPolicy others; do
+ # continue with empty and commented lines.
+ [ -z "$status" -o "$status" = "#" ] && continue
+
+ # can only run positive tests. Positive validation
+ # status is the exit condition for the code in the library.
+ [ $status -ne 0 ] && continue;
+ extraOpt=""
+ if [ "$explPolicy" -a "$explPolicy" != "undef" ]; then
+ extraOpt="-p -o $explPolicy"
+ fi
+ cmd="vfychain -d $DB_DIR $extraOpt $CERT_DIR/$leafCert.cert"
+ if [ -n "$MEMLEAK_DBG" ]; then
+ cmd="$RUN_COMMAND_DBG $cmd"
+ fi
+ echo $cmd
+ $cmd > $tmpLogFile
+ if [ -z "$MEMLEAK_DBG" ]; then
+ cat $tmpLogFile
+ grep "Memory Leak:" $tmpLogFile
+ html_msg $? 1 "Object leak tests with $leafCert certificate"
+ else
+ cat $tmpLogFile >> $LOGFILE
+ fi
+ done < $QADIR/libpkix/vfychain_test.lst
+
+ if [ -n "${MEMLEAK_DBG}" ]; then
+ log_parse
+ ret=$?
+ html_msg ${ret} 0 "${LOGNAME}" \
+ "produced a returncode of $ret, expected is 0"
+ html "</TABLE><BR>"
+ fi
+}
+
+
################## main #################################################
libpkix_init
-libpkix_main | tee ${LIBPKIX_LOG}
-libpkix_cleanup
+libpkix_setup_db
+if [ "$PKIX_OBJECT_LEAK_TEST" ]; then
+ libpkix_leak_test
+ if [ -n "${MEMLEAK_DBG}" ]; then
+ libpkix_cleanup
+ return 1
+ fi
+fi
+# place other tests here
+# Run libpkix unit tests at the end
+if [ "$BUILD_LIBPKIX_TEST" ]; then
+ libpkix_UT_main | tee ${LIBPKIX_LOG}
+fi
+libpkix_cleanup
diff --git a/security/nss/tests/memleak/memleak.sh b/security/nss/tests/memleak/memleak.sh
index 5c72156b1..f58cb9856 100644
--- a/security/nss/tests/memleak/memleak.sh
+++ b/security/nss/tests/memleak/memleak.sh
@@ -845,12 +845,32 @@ run_ocsp()
stat_print "Ocspclnt"
}
+############################### run_pkix ###############################
+# local shell function to run ocsp tests
+########################################################################
+run_pkix()
+{
+ [ -z "$PKIX_OBJECT_LEAK_TEST" ] && return
+ stat_clear
+
+ cd ${QADIR}/libpkix
+ . ./libpkix.sh
+
+ stat_print "Libpkix"
+}
+
################################# main #################################
memleak_init
-run_ciphers_server
-run_ciphers_client
+# Can not run pkix object/memory leak tests with server/client tests.
+# Pkix test is single-threaded by design. OCSP tests are ok.
+if [ -z "$PKIX_OBJECT_LEAK_TEST" ]; then
+ run_ciphers_server
+ run_ciphers_client
+else
+ run_pkix
+fi
run_ocsp
cnt_total