From 62d731d2c2755b5f2a70e5959415f81c4bb2d7fb Mon Sep 17 00:00:00 2001 From: John Schanck Date: Mon, 25 May 2026 10:22:44 +0200 Subject: [PATCH] Bug 2029818 - avoid refcount over-release in CERT_CertChainFromCert error path. --- security/nss/lib/certhigh/certhigh.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c index 7ae80b193e..18956e18e4 100644 --- a/security/nss/lib/certhigh/certhigh.c +++ b/security/nss/lib/certhigh/certhigh.c @@ -1035,7 +1035,7 @@ CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, NSSCertificate *stanCert; PLArenaPool *arena; NSSUsage nssUsage; - int i, len; + int i = 0, len; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSCryptoContext *cc = STAN_GetDefaultCryptoContext(); @@ -1072,7 +1072,6 @@ CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, chain->certs = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem)); if (!chain->certs) goto loser; - i = 0; stanCert = stanChain[i]; while (stanCert) { SECItem derCert; @@ -1084,7 +1083,7 @@ CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, derCert.data = (unsigned char *)stanCert->encoding.data; derCert.type = siBuffer; if (SECITEM_CopyItem(arena, &chain->certs[i], &derCert) != SECSuccess) { - CERT_DestroyCertificate(cCert); + /* loser: will release stanChain[i]; don't release it here too. */ goto loser; } stanCert = stanChain[++i]; @@ -1106,7 +1105,9 @@ CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage, nss_ZFreeIf(stanChain); return chain; loser: - i = 0; + /* Release only the chain entries not already released by the copy + * loop above; entries 0..i-1 have already had their BuildChain + * reference dropped, so start at i to avoid an over-release. */ stanCert = stanChain[i]; while (stanCert) { CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);