Index: nss/lib/ckfw/builtins/bfind.c |
diff --git a/nss/lib/ckfw/builtins/bfind.c b/nss/lib/ckfw/builtins/bfind.c |
index e31c4ef099875e88d7614675bb56c21409c55089..df35ed8b689ff7e15dbab424391d8d86ade2d39f 100644 |
--- a/nss/lib/ckfw/builtins/bfind.c |
+++ b/nss/lib/ckfw/builtins/bfind.c |
@@ -183,7 +183,16 @@ nss_builtins_FindObjectsInit |
NSSArena *arena; |
NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL; |
struct builtinsFOStr *fo = (struct builtinsFOStr *)NULL; |
- builtinsInternalObject **temp = (builtinsInternalObject **)NULL; |
+ |
+ /* |
+ * 99% of the time we get 0 or 1 matches. So we start with a small |
+ * stack-allocated array to hold the matches and switch to a heap-allocated |
+ * array later if the number of matches exceeds STACK_BUF_LENGTH. |
+ */ |
+ #define STACK_BUF_LENGTH 1 |
+ builtinsInternalObject *stackTemp[STACK_BUF_LENGTH]; |
+ builtinsInternalObject **temp = stackTemp; |
+ PRBool tempIsHeapAllocated = PR_FALSE; |
PRUint32 i; |
arena = NSSArena_Create(); |
@@ -211,17 +220,24 @@ nss_builtins_FindObjectsInit |
rv->Next = builtins_mdFindObjects_Next; |
rv->null = (void *)NULL; |
- temp = nss_ZNEWARRAY((NSSArena *)NULL, builtinsInternalObject *, |
- nss_builtins_nObjects); |
- if( (builtinsInternalObject **)NULL == temp ) { |
- *pError = CKR_HOST_MEMORY; |
- goto loser; |
- } |
- |
for( i = 0; i < nss_builtins_nObjects; i++ ) { |
builtinsInternalObject *o = (builtinsInternalObject *)&nss_builtins_data[i]; |
if( CK_TRUE == builtins_match(pTemplate, ulAttributeCount, o) ) { |
+ if( fo->n == STACK_BUF_LENGTH ) { |
+ /* Switch from the small stack array to a heap-allocated array large |
+ * enough to handle matches in all remaining cases. */ |
+ temp = nss_ZNEWARRAY((NSSArena *)NULL, builtinsInternalObject *, |
+ fo->n + nss_builtins_nObjects - i); |
+ if( (builtinsInternalObject **)NULL == temp ) { |
+ *pError = CKR_HOST_MEMORY; |
+ goto loser; |
+ } |
+ tempIsHeapAllocated = PR_TRUE; |
+ (void)nsslibc_memcpy(temp, stackTemp, |
+ sizeof(builtinsInternalObject *) * fo->n); |
+ } |
+ |
temp[ fo->n ] = o; |
fo->n++; |
} |
@@ -234,13 +250,17 @@ nss_builtins_FindObjectsInit |
} |
(void)nsslibc_memcpy(fo->objs, temp, sizeof(builtinsInternalObject *) * fo->n); |
- nss_ZFreeIf(temp); |
- temp = (builtinsInternalObject **)NULL; |
+ if (tempIsHeapAllocated) { |
+ nss_ZFreeIf(temp); |
+ temp = (builtinsInternalObject **)NULL; |
+ } |
return rv; |
loser: |
- nss_ZFreeIf(temp); |
+ if (tempIsHeapAllocated) { |
+ nss_ZFreeIf(temp); |
+ } |
nss_ZFreeIf(fo); |
nss_ZFreeIf(rv); |
if ((NSSArena *)NULL != arena) { |