diff options
author | alexei.volkov.bugs%sun.com <devnull@localhost> | 2008-03-26 18:49:05 +0000 |
---|---|---|
committer | alexei.volkov.bugs%sun.com <devnull@localhost> | 2008-03-26 18:49:05 +0000 |
commit | 97412bfb962279506fd1b7720311395b6d76424a (patch) | |
tree | 31649733bc2b8c28c36bd4e5e0451e727cc41fe5 /security | |
parent | 9376585d5529b650b8210d1cbcc88c3264be521e (diff) | |
download | nss-hg-97412bfb962279506fd1b7720311395b6d76424a.tar.gz |
397832 - libpkix leaks memory if a macro calls a function that returns an error. Object leak test. r=nelson
Diffstat (limited to 'security')
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(¶llelFnInvocationCount); + 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(¶llelFnInvocationCount); +#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(¶llelFnInvocationCount); + 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(¶llelFnInvocationCount); +#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 |