[pypy-commit] pypy default: Merged in detect_egd2 (pull request #333)

vext01 noreply at buildbot.pypy.org
Tue Sep 22 17:55:16 CEST 2015


Author: Edd Barrett <vext01 at gmail.com>
Branch: 
Changeset: r79775:7a75425fd561
Date: 2015-09-22 16:55 +0100
http://bitbucket.org/pypy/pypy/changeset/7a75425fd561/

Log:	Merged in detect_egd2 (pull request #333)

	Deal with platforms without RAND_egd().

diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -241,20 +241,26 @@
         res = libssl_RAND_status()
         return space.wrap(res)
 
-    @unwrap_spec(path=str)
-    def RAND_egd(space, path):
-        """RAND_egd(path) -> bytes
+    if HAVE_OPENSSL_RAND_EGD:
+        @unwrap_spec(path=str)
+        def RAND_egd(space, path):
+            """RAND_egd(path) -> bytes
 
-        Queries the entropy gather daemon (EGD) on socket path.  Returns number
-        of bytes read.  Raises socket.sslerror if connection to EGD fails or
-        if it does provide enough data to seed PRNG."""
-        with rffi.scoped_str2charp(path) as socket_path:
-            bytes = libssl_RAND_egd(socket_path)
-        if bytes == -1:
-            raise ssl_error(space,
-                            "EGD connection failed or EGD did not return "
-                            "enough data to seed the PRNG")
-        return space.wrap(bytes)
+            Queries the entropy gather daemon (EGD) on socket path.  Returns number
+            of bytes read.  Raises socket.sslerror if connection to EGD fails or
+            if it does provide enough data to seed PRNG."""
+            with rffi.scoped_str2charp(path) as socket_path:
+                bytes = libssl_RAND_egd(socket_path)
+            if bytes == -1:
+                raise ssl_error(space,
+                                "EGD connection failed or EGD did not return "
+                                "enough data to seed the PRNG")
+            return space.wrap(bytes)
+    else:
+        # Dummy func for platforms missing RAND_egd(). Most likely LibreSSL.
+        @unwrap_spec(path=str)
+        def RAND_egd(space, path):
+            raise ssl_error(space, "RAND_egd unavailable")
 
 
 class _SSLSocket(W_Root):
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -36,7 +36,8 @@
         assert isinstance(_ssl.OPENSSL_VERSION_INFO, tuple)
         assert len(_ssl.OPENSSL_VERSION_INFO) == 5
         assert isinstance(_ssl.OPENSSL_VERSION, str)
-        assert 'openssl' in _ssl.OPENSSL_VERSION.lower()
+        lower_version = _ssl.OPENSSL_VERSION.lower()
+        assert 'openssl' in lower_version or "libressl" in lower_version
 
         assert isinstance(_ssl.ALERT_DESCRIPTION_ACCESS_DENIED, int)
 
@@ -69,8 +70,9 @@
 
     def test_sslwrap(self):
         import _ssl, _socket, sys, gc
-        if sys.platform == 'darwin' or 'freebsd' in sys.platform:
-            skip("hangs indefinitely on OSX & FreeBSD (also on CPython)")
+        if sys.platform == 'darwin' or 'freebsd' in sys.platform or \
+                'openbsd' in sys.platform:
+            skip("hangs indefinitely on OSX & BSD (also on CPython)")
         s = _socket.socket()
         if sys.version_info < (2, 7, 9):
             ss = _ssl.sslwrap(s, 0)
diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py
--- a/rpython/rlib/ropenssl.py
+++ b/rpython/rlib/ropenssl.py
@@ -264,6 +264,9 @@
     OPENSSL_NO_ECDH = True
 HAS_ALPN = OPENSSL_VERSION_NUMBER >= 0x1000200fL and not OPENSSL_NO_TLSEXT
 
+HAVE_OPENSSL_RAND_EGD = rffi_platform.has('RAND_egd("/")',
+                                          '#include <openssl/rand.h>',
+                                          libraries=['ssl', 'crypto'])
 
 def external(name, argtypes, restype, **kw):
     kw['compilation_info'] = eci
@@ -288,7 +291,8 @@
 if HAVE_OPENSSL_RAND:
     ssl_external('RAND_add', [rffi.CCHARP, rffi.INT, rffi.DOUBLE], lltype.Void)
     ssl_external('RAND_status', [], rffi.INT)
-    ssl_external('RAND_egd', [rffi.CCHARP], rffi.INT)
+    if HAVE_OPENSSL_RAND_EGD:
+        ssl_external('RAND_egd', [rffi.CCHARP], rffi.INT)
 ssl_external('SSL_CTX_new', [SSL_METHOD], SSL_CTX)
 ssl_external('SSL_get_SSL_CTX', [SSL], SSL_CTX)
 ssl_external('SSL_set_SSL_CTX', [SSL, SSL_CTX], SSL_CTX)
diff --git a/rpython/rtyper/tool/rffi_platform.py b/rpython/rtyper/tool/rffi_platform.py
--- a/rpython/rtyper/tool/rffi_platform.py
+++ b/rpython/rtyper/tool/rffi_platform.py
@@ -17,12 +17,15 @@
 #
 # Helpers for simple cases
 
-def eci_from_header(c_header_source, include_dirs=None):
+def eci_from_header(c_header_source, include_dirs=None, libraries=None):
     if include_dirs is None:
         include_dirs = []
+    if libraries is None:
+        libraries = []
     return ExternalCompilationInfo(
         post_include_bits=[c_header_source],
-        include_dirs=include_dirs
+        include_dirs=include_dirs,
+        libraries=libraries,
     )
 
 def getstruct(name, c_header_source, interesting_fields):
@@ -75,9 +78,10 @@
         CConfig._compilation_info_.includes = includes
     return configure(CConfig)['RESULT']
 
-def has(name, c_header_source, include_dirs=None):
+def has(name, c_header_source, include_dirs=None, libraries=None):
     class CConfig:
-        _compilation_info_ = eci_from_header(c_header_source, include_dirs)
+        _compilation_info_ = \
+            eci_from_header(c_header_source, include_dirs, libraries)
         HAS = Has(name)
     return configure(CConfig)['HAS']
 
diff --git a/rpython/rtyper/tool/test/test_rffi_platform.py b/rpython/rtyper/tool/test/test_rffi_platform.py
--- a/rpython/rtyper/tool/test/test_rffi_platform.py
+++ b/rpython/rtyper/tool/test/test_rffi_platform.py
@@ -270,12 +270,34 @@
                                        [("d_name", lltype.FixedSizeArray(rffi.CHAR, 1))])
     assert dirent.c_d_name.length == 32
 
-def test_has():
+def test_has_0001():
     assert rffi_platform.has("x", "int x = 3;")
     assert not rffi_platform.has("x", "")
     # has() should also not crash if it is given an invalid #include
     assert not rffi_platform.has("x", "#include <some/path/which/cannot/exist>")
 
+def test_has_0002():
+    assert rffi_platform.has("pow", "#include <math.h>", libraries=["m"])
+
+def test_has_0003():
+    """multiple libraries"""
+    assert rffi_platform.has("pow", "#include <math.h>", libraries=["m", "c"])
+
+def test_has_0004():
+    """bogus symbol name"""
+    assert not rffi_platform.has("pow", "#include <math.h>",
+                                 libraries=["boguslibname"])
+
+def test_has_0005():
+    """bogus symbol name and lib name"""
+    assert not rffi_platform.has("bogus_symbol_name", "#include <math.h>",
+                                 libraries=["boguslibname"])
+
+def test_has_0006():
+    """missing include"""
+    assert not rffi_platform.has("pow", "", libraries=["m"])
+
+
 def test_verify_eci():
     eci = ExternalCompilationInfo()
     rffi_platform.verify_eci(eci)


More information about the pypy-commit mailing list