crypt32(3/13): Correct reference counting when deleting contexts from collections

View: New views
1 Messages — Rating Filter:   Alert me  

crypt32(3/13): Correct reference counting when deleting contexts from collections

by Juan Lang-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I sent essentially the same patch before.  I improved the comments in
this version.
--Juan

[0003-Correct-reference-counting-when-deleting-contexts-fr.patch]

From 84859e0fb45e86aa08eb676a982f3d76337062dc Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang@...>
Date: Tue, 3 Nov 2009 17:04:32 -0800
Subject: [PATCH] Correct reference counting when deleting contexts from collections

---
 dlls/crypt32/collectionstore.c |   34 ++++++++++++++++++++++++++++------
 dlls/crypt32/tests/store.c     |   22 ++++++++++++++++++++++
 2 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/dlls/crypt32/collectionstore.c b/dlls/crypt32/collectionstore.c
index 12eb7c3..e55c1bf 100644
--- a/dlls/crypt32/collectionstore.c
+++ b/dlls/crypt32/collectionstore.c
@@ -255,11 +255,19 @@ static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store,
  void *pCertContext)
 {
     BOOL ret;
+    PCCERT_CONTEXT linked;
 
     TRACE("(%p, %p)\n", store, pCertContext);
 
-    ret = CertDeleteCertificateFromStore(
-     Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT)));
+    /* Deleting the linked context results in its ref count getting
+     * decreased, but the caller of this (CertDeleteCertificateFromStore) also
+     * decreases pCertContext's ref count, by calling
+     * CertFreeCertificateContext.  Increase ref count of linked context to
+     * compensate.
+     */
+    linked = Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT));
+    CertDuplicateCertificateContext(linked);
+    ret = CertDeleteCertificateFromStore(linked);
     return ret;
 }
 
@@ -333,11 +341,18 @@ static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store,
  void *pCrlContext)
 {
     BOOL ret;
+    PCCRL_CONTEXT linked;
 
     TRACE("(%p, %p)\n", store, pCrlContext);
 
-    ret = CertDeleteCRLFromStore(
-     Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT)));
+    /* Deleting the linked context results in its ref count getting
+     * decreased, but the caller of this (CertDeleteCRLFromStore) also
+     * decreases pCrlContext's ref count, by calling CertFreeCRLContext.
+     * Increase ref count of linked context to compensate.
+     */
+    linked = Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT));
+    CertDuplicateCRLContext(linked);
+    ret = CertDeleteCRLFromStore(linked);
     return ret;
 }
 
@@ -411,11 +426,18 @@ static BOOL CRYPT_CollectionDeleteCTL(PWINECRYPT_CERTSTORE store,
  void *pCtlContext)
 {
     BOOL ret;
+    PCCTL_CONTEXT linked;
 
     TRACE("(%p, %p)\n", store, pCtlContext);
 
-    ret = CertDeleteCTLFromStore(
-     Context_GetLinkedContext(pCtlContext, sizeof(CTL_CONTEXT)));
+    /* Deleting the linked context results in its ref count getting
+     * decreased, but the caller of this (CertDeleteCTLFromStore) also
+     * decreases pCtlContext's ref count, by calling CertFreeCTLContext.
+     * Increase ref count of linked context to compensate.
+     */
+    linked = Context_GetLinkedContext(pCtlContext, sizeof(CTL_CONTEXT));
+    CertDuplicateCTLContext(linked);
+    ret = CertDeleteCTLFromStore(linked);
     return ret;
 }
 
diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c
index 88f53ed..1f6609c 100644
--- a/dlls/crypt32/tests/store.c
+++ b/dlls/crypt32/tests/store.c
@@ -574,6 +574,28 @@ static void testCollectionStore(void)
     CertCloseStore(collection, 0);
     CertCloseStore(store2, 0);
     CertCloseStore(store1, 0);
+
+    /* Test adding certificates to and deleting certificates from collections.
+     */
+    store1 = CertOpenSystemStoreA(0, "My");
+    collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
+     CERT_STORE_CREATE_NEW_FLAG, NULL);
+
+    ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
+     bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
+    ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
+    CertDeleteCertificateFromStore(context);
+
+    CertAddStoreToCollection(collection, store1,
+     CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
+
+    ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
+     bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
+    ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
+    CertDeleteCertificateFromStore(context);
+
+    CertCloseStore(collection, 0);
+    CertCloseStore(store1, 0);
 }
 
 /* Looks for the property with ID propID in the buffer buf.  Returns a pointer
--
1.6.0.6