[System]: Fix minor leaks in AppleTls. (#5369)
authorMartin Baulig <mabaul@microsoft.com>
Tue, 15 Aug 2017 17:08:12 +0000 (13:08 -0400)
committerGitHub <noreply@github.com>
Tue, 15 Aug 2017 17:08:12 +0000 (13:08 -0400)
These should be automatically collected by the GC, but explicitly disposing
will keep memory usage more stable over time and keep pressure off the GC.

mcs/class/System/Mono.AppleTls/AppleCertificateHelper.cs
mcs/class/System/Mono.AppleTls/AppleTlsContext.cs
mcs/class/System/Mono.AppleTls/Trust.cs

index d3b29fa2721179ad4337eff51a0b33239b3a3801..710433ef071619a21464d6a07c31f1eafc12cff0 100644 (file)
@@ -133,28 +133,28 @@ namespace Mono.AppleTls
                                        targetHost = targetHost.Substring (0, pos);
                        }
 
-                       var policy = SecPolicy.CreateSslPolicy (!serverMode, targetHost);
-                       var trust = new SecTrust (certificates, policy);
-
-                       if (validator.Settings.TrustAnchors != null) {
-                               var status = trust.SetAnchorCertificates (validator.Settings.TrustAnchors);
-                               if (status != SecStatusCode.Success)
-                                       throw new InvalidOperationException (status.ToString ());
-                               trust.SetAnchorCertificatesOnly (false);
-                       }
-
-                       if (validator.Settings.CertificateValidationTime != null) {
-                               var status = trust.SetVerifyDate (validator.Settings.CertificateValidationTime.Value);
-                               if (status != SecStatusCode.Success)
-                                       throw new InvalidOperationException (status.ToString ());
+                       using (var policy = SecPolicy.CreateSslPolicy (!serverMode, targetHost))
+                       using (var trust = new SecTrust (certificates, policy)) {
+                               if (validator.Settings.TrustAnchors != null) {
+                                       var status = trust.SetAnchorCertificates (validator.Settings.TrustAnchors);
+                                       if (status != SecStatusCode.Success)
+                                               throw new InvalidOperationException (status.ToString ());
+                                       trust.SetAnchorCertificatesOnly (false);
+                               }
+
+                               if (validator.Settings.CertificateValidationTime != null) {
+                                       var status = trust.SetVerifyDate (validator.Settings.CertificateValidationTime.Value);
+                                       if (status != SecStatusCode.Success)
+                                               throw new InvalidOperationException (status.ToString ());
+                               }
+
+                               var result = trust.Evaluate ();
+                               if (result == SecTrustResult.Unspecified)
+                                       return true;
+
+                               errors |= MonoSslPolicyErrors.RemoteCertificateChainErrors;
+                               return false;
                        }
-
-                       var result = trust.Evaluate ();
-                       if (result == SecTrustResult.Unspecified)
-                               return true;
-
-                       errors |= MonoSslPolicyErrors.RemoteCertificateChainErrors;
-                       return false;
                }
        }
 }
index bb42f79e6ee38fc1979c95963c16e77771fc57d3..1d53227f5e9777b78de91c2287cea8b2c5c8edf9 100644 (file)
@@ -234,32 +234,41 @@ namespace Mono.AppleTls
                         * 
                         */
 
-                       var trust = GetPeerTrust (!IsServer);
-                       X509CertificateCollection certificates;
+                       bool ok;
+                       SecTrust trust = null;
+                       X509CertificateCollection certificates = null;
 
-                       if (trust == null || trust.Count == 0) {
-                               remoteCertificate = null;
-                               if (!IsServer)
-                                       throw new TlsException (AlertDescription.CertificateUnknown);
-                               certificates = null;
-                       } else {
-                               if (trust.Count > 1)
-                                       Debug ("WARNING: Got multiple certificates in SecTrust!");
+                       try {
+                               trust = GetPeerTrust (!IsServer);
 
-                               certificates = new X509CertificateCollection ();
-                               for (int i = 0; i < trust.Count; i++)
-                                       certificates.Add (trust [(IntPtr)i].ToX509Certificate ());
+                               if (trust == null || trust.Count == 0) {
+                                       remoteCertificate = null;
+                                       if (!IsServer)
+                                               throw new TlsException (AlertDescription.CertificateUnknown);
+                                       certificates = null;
+                               } else {
+                                       if (trust.Count > 1)
+                                               Debug ("WARNING: Got multiple certificates in SecTrust!");
 
-                               remoteCertificate = certificates [0];
-                               Debug ("Got peer trust: {0}", remoteCertificate);
-                       }
+                                       certificates = new X509CertificateCollection ();
+                                       for (int i = 0; i < trust.Count; i++)
+                                               certificates.Add (trust.GetCertificate (i));
+
+                                       remoteCertificate = new X509Certificate (certificates [0]);
+                                       Debug ("Got peer trust: {0}", remoteCertificate);
+                               }
 
-                       bool ok;
-                       try {
                                ok = ValidateCertificate (certificates);
                        } catch (Exception ex) {
                                Debug ("Certificate validation failed: {0}", ex);
                                throw new TlsException (AlertDescription.CertificateUnknown, "Certificate validation threw exception.");
+                       } finally {
+                               if (trust != null)
+                                       trust.Dispose ();
+                               if (certificates != null) {
+                                       for (int i = 0; i < certificates.Count; i++)
+                                               certificates [i].Dispose ();
+                               }
                        }
 
                        if (!ok)
index 33a505043e813768b24d5d970360d827dd3d21c2..38778f109b0248eb9d861a8324adda4547985b20 100644 (file)
@@ -66,6 +66,8 @@ namespace Mono.AppleTls {
                        foreach (var certificate in certificates)
                                array [i++] = new SecCertificate (certificate);
                        Initialize (array, policy);
+                       for (i = 0; i < array.Length; i++)
+                               array [i].Dispose ();
                }
 
                void Initialize (SecCertificate[] array, SecPolicy policy)
@@ -122,6 +124,17 @@ namespace Mono.AppleTls {
                        }
                }
 
+               internal X509Certificate GetCertificate (int index)
+               {
+                       if (handle == IntPtr.Zero)
+                               throw new ObjectDisposedException ("SecTrust");
+                       if (((long)index < 0) || ((long)index >= Count))
+                               throw new ArgumentOutOfRangeException ("index");
+
+                       var ptr = SecTrustGetCertificateAtIndex (handle, (IntPtr)index);
+                       return new X509Certificate (ptr);
+               }
+
                [DllImport (AppleTlsContext.SecurityLibrary)]
                extern static SecStatusCode /* OSStatus */ SecTrustSetAnchorCertificates (IntPtr /* SecTrustRef */ trust, IntPtr /* CFArrayRef */ anchorCertificates);