Merge pull request #94 from pyca/coveralls

Integrate with Coveralls
diff --git a/ChangeLog b/ChangeLog
index e36f2d2..164c9ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -17,6 +17,13 @@
 	* OpenSSL/tsafe.py: Replace the use of ``apply`` (which has been
 	  removed in Python 3) with the equivalent syntax.
 
+2014-03-28  Jonathan Giannuzzi  <jonathan@giannuzzi.be>
+
+	* OpenSSL/crypto.py: Fix memory leak in _X509_REVOKED_dup.
+	* leakcheck/crypto.py: Add checks for _X509_REVOKED_dup, CRL.add_revoked
+	  and CRL.get_revoked.
+	* setup.py: Require cryptography 0.3 to have the ASN1_TIME_free binding.
+
 2014-03-02  Stephen Holsapple  <sholsapp@gmail.com>
 
 	* OpenSSL/crypto.py: Add ``get_extensions`` method to ``X509Req``.
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index ed0b629..65e28d7 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -1323,9 +1323,11 @@
         _raise_current_error()
 
     if original.serialNumber != _ffi.NULL:
+        _lib.ASN1_INTEGER_free(copy.serialNumber)
         copy.serialNumber = _lib.ASN1_INTEGER_dup(original.serialNumber)
 
     if original.revocationDate != _ffi.NULL:
+        _lib.ASN1_TIME_free(copy.revocationDate)
         copy.revocationDate = _lib.M_ASN1_TIME_dup(original.revocationDate)
 
     if original.extensions != _ffi.NULL:
diff --git a/leakcheck/crypto.py b/leakcheck/crypto.py
index 6a9af92..f5fe2f8 100644
--- a/leakcheck/crypto.py
+++ b/leakcheck/crypto.py
@@ -4,7 +4,10 @@
 import sys
 
 from OpenSSL.crypto import (
-    FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey)
+    FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked,
+    _X509_REVOKED_dup)
+
+from OpenSSL._util import lib as _lib
 
 
 
@@ -101,6 +104,47 @@
                 pass
 
 
+
+class Checker_CRL(BaseChecker):
+    """
+    Leak checks for L{CRL.add_revoked} and L{CRL.get_revoked}.
+    """
+    def check_add_revoked(self):
+        """
+        Call the add_revoked method repeatedly on an empty CRL.
+        """
+        for i in xrange(self.iterations * 200):
+            CRL().add_revoked(Revoked())
+
+
+    def check_get_revoked(self):
+        """
+        Create a CRL object with 100 Revoked objects, then call the
+        get_revoked method repeatedly.
+        """
+        crl = CRL()
+        for i in xrange(100):
+            crl.add_revoked(Revoked())
+        for i in xrange(self.iterations):
+            crl.get_revoked()
+
+
+
+class Checker_X509_REVOKED_dup(BaseChecker):
+    """
+    Leak checks for :py:obj:`_X509_REVOKED_dup`.
+    """
+    def check_X509_REVOKED_dup(self):
+        """
+        Copy an empty Revoked object repeatedly. The copy is not garbage
+        collected, therefore it needs to be manually freed.
+        """
+        for i in xrange(self.iterations * 100):
+            revoked_copy = _X509_REVOKED_dup(Revoked()._revoked)
+            _lib.X509_REVOKED_free(revoked_copy)
+
+
+
 def vmsize():
     return [x for x in file('/proc/self/status').readlines() if 'VmSize' in x]