Bug 1281955 - Don't Adopt() NSS allocated strings in PSM to avoid using the wrong deallocator. draft
authorCykesiopka <cykesiopka.bmo@gmail.com>
Wed, 29 Jun 2016 18:42:37 -0700
changeset 382613 4d736d63db16238700a105ab420b44973ba1e778
parent 382375 81f94d11a924952a11d91a6078fd80e3bdb7087c
child 524255 559ce78862596f293c4715d292300dc817cfb3a9
push id21787
push usercykesiopka.bmo@gmail.com
push dateThu, 30 Jun 2016 01:47:55 +0000
bugs1281955, 1281564
milestone50.0a1
Bug 1281955 - Don't Adopt() NSS allocated strings in PSM to avoid using the wrong deallocator. There are a few places in PSM where the result of an NSS function returning char* is adopted by e.g. an nsXPIDLCString, which will use the wrong deallocator when the string eventually gets destroyed. This is basically Bug 1281564, but the free() call is buried within the Mozilla string code instead. MozReview-Commit-ID: HVSMyRpLnjS
security/manager/ssl/nsNSSCertHelper.cpp
security/manager/ssl/nsNSSCertificateDB.cpp
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -111,41 +111,46 @@ ProcessVersion(SECItem* versionItem, nsI
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   printableItem.forget(retItem);
   return NS_OK;
 }
 
-static nsresult 
-ProcessSerialNumberDER(SECItem         *serialItem, 
-                       nsINSSComponent *nssComponent,
-                       nsIASN1PrintableItem **retItem)
+static nsresult
+ProcessSerialNumberDER(const SECItem& serialItem,
+                       NotNull<nsINSSComponent*> nssComponent,
+               /*out*/ nsCOMPtr<nsIASN1PrintableItem>& retItem)
 {
-  nsresult rv;
   nsAutoString text;
-  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
-
-  rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text); 
-  if (NS_FAILED(rv))
+  nsresult rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text);
+  if (NS_FAILED(rv)) {
     return rv;
+  }
 
+  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
   rv = printableItem->SetDisplayName(text);
-  if (NS_FAILED(rv))
+  if (NS_FAILED(rv)) {
     return rv;
+  }
 
-  nsXPIDLCString serialNumber;
-  serialNumber.Adopt(CERT_Hexify(serialItem, 1));
-  if (!serialNumber)
+  UniquePORTString serialNumber(
+    CERT_Hexify(const_cast<SECItem*>(&serialItem), 1));
+  if (!serialNumber) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
-  rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber));
-  printableItem.forget(retItem);
-  return rv;
+  rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber.get()));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  retItem = printableItem.forget();
+  return NS_OK;
 }
 
 static nsresult
 GetDefaultOIDFormat(SECItem *oid,
                     nsINSSComponent *nssComponent,
                     nsAString &outString,
                     char separator)
 {
@@ -1810,16 +1815,19 @@ static SECStatus RegisterDynamicOids()
   registered = true;
   return rv;
 }
 
 nsresult
 nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
                                                  nsINSSComponent *nssComponent)
 {
+  MOZ_ASSERT(nssComponent);
+  NS_ENSURE_ARG(nssComponent);
+
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
   if (RegisterDynamicOids() != SECSuccess)
     return NS_ERROR_FAILURE;
 
   //
@@ -1853,20 +1861,19 @@ nsNSSCertificate::CreateTBSCertificateAS
   sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
 
   nsresult rv = ProcessVersion(&mCert->version, nssComponent,
                                getter_AddRefs(printableItem));
   if (NS_FAILED(rv))
     return rv;
 
   asn1Objects->AppendElement(printableItem, false);
-  
-  rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent,
-                              getter_AddRefs(printableItem));
 
+  rv = ProcessSerialNumberDER(mCert->serialNumber, WrapNotNull(nssComponent),
+                              printableItem);
   if (NS_FAILED(rv))
     return rv;
   asn1Objects->AppendElement(printableItem, false);
 
   nsCOMPtr<nsIASN1Sequence> algID;
   rv = ProcessSECAlgorithmID(&mCert->signature,
                              nssComponent, getter_AddRefs(algID));
   if (NS_FAILED(rv))
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -375,18 +375,17 @@ nsNSSCertificateDB::handleCACertDownload
   rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
   if (NS_FAILED(rv))
     return rv;
 
   if (!allows)
     return NS_ERROR_NOT_AVAILABLE;
 
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trust is %d\n", trustBits));
-  nsXPIDLCString nickname;
-  nickname.Adopt(CERT_MakeCANickname(tmpCert.get()));
+  UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));
 
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
 
   nsNSSCertTrust trust;
   trust.SetValidCA();
   trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
                    !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
                    !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));
@@ -1402,18 +1401,17 @@ NS_IMETHODIMP nsNSSCertificateDB::AddCer
   }
 
    // If there's already a certificate that matches this one in the database,
    // we still want to set its trust to the given value.
   if (tmpCert->isperm) {
     return SetCertTrustFromString(newCert, aTrust);
   }
 
-  nsXPIDLCString nickname;
-  nickname.Adopt(CERT_MakeCANickname(tmpCert.get()));
+  UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));
 
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));
 
   rv = attemptToLogInWithDefaultPassword();
   if (NS_WARN_IF(rv != NS_OK)) {
     return rv;
   }