[pypy-commit] pypy default: Fix: _hashlib was just broken for any non-standard hash function.

arigo noreply at buildbot.pypy.org
Sun Dec 11 12:48:39 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r50375:2e5b6dce5753
Date: 2011-12-11 12:48 +0100
http://bitbucket.org/pypy/pypy/changeset/2e5b6dce5753/

Log:	Fix: _hashlib was just broken for any non-standard hash function.

	Small extra clean-ups.

diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -21,11 +21,11 @@
 
 class W_Hash(Wrappable):
     ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
-    _block_size = -1
 
     def __init__(self, space, name):
         self.name = name
-        self.digest_size = self.compute_digest_size()
+        digest_type = self.digest_type_by_name(space)
+        self.digest_size = rffi.getintfield(digest_type, 'c_md_size')
 
         # Allocate a lock for each HASH object.
         # An optimization would be to not release the GIL on small requests,
@@ -34,21 +34,22 @@
 
         ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
         rgc.add_memory_pressure(HASH_MALLOC_SIZE + self.digest_size)
+        ropenssl.EVP_DigestInit(ctx, digest_type)
         self.ctx = ctx
 
-    def initdigest(self, space, name):
-        digest = ropenssl.EVP_get_digestbyname(name)
-        if not digest:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("unknown hash function"))
-        ropenssl.EVP_DigestInit(self.ctx, digest)
-
     def __del__(self):
         # self.lock.free()
         if self.ctx:
             ropenssl.EVP_MD_CTX_cleanup(self.ctx)
             lltype.free(self.ctx, flavor='raw')
 
+    def digest_type_by_name(self, space):
+        digest_type = ropenssl.EVP_get_digestbyname(self.name)
+        if not digest_type:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("unknown hash function"))
+        return digest_type
+
     def descr_repr(self, space):
         addrstring = self.getaddrstring(space)
         return space.wrap("<%s HASH object at 0x%s>" % (
@@ -87,7 +88,9 @@
         return space.wrap(self.digest_size)
 
     def get_block_size(self, space):
-        return space.wrap(self.compute_block_size())
+        digest_type = self.digest_type_by_name(space)
+        block_size = rffi.getintfield(digest_type, 'c_block_size')
+        return space.wrap(block_size)
 
     def _digest(self, space):
         with lltype.scoped_alloc(ropenssl.EVP_MD_CTX.TO) as ctx:
@@ -99,36 +102,6 @@
                 ropenssl.EVP_MD_CTX_cleanup(ctx)
                 return rffi.charpsize2str(digest, digest_size)
 
-    def compute_digest_size(self):
-        # XXX This isn't the nicest way, but the EVP_MD_size OpenSSL
-        # XXX function is defined as a C macro on OS X and would be
-        # XXX significantly harder to implement in another way.
-        # Values are digest sizes in bytes
-        return {
-            'md5':    16, 'MD5':    16,
-            'sha1':   20, 'SHA1':   20,
-            'sha224': 28, 'SHA224': 28,
-            'sha256': 32, 'SHA256': 32,
-            'sha384': 48, 'SHA384': 48,
-            'sha512': 64, 'SHA512': 64,
-            }.get(self.name, 0)
-
-    def compute_block_size(self):
-        if self._block_size != -1:
-            return self._block_size
-        # XXX This isn't the nicest way, but the EVP_MD_CTX_block_size
-        # XXX OpenSSL function is defined as a C macro on some systems
-        # XXX and would be significantly harder to implement in
-        # XXX another way.
-        self._block_size = {
-            'md5':     64, 'MD5':     64,
-            'sha1':    64, 'SHA1':    64,
-            'sha224':  64, 'SHA224':  64,
-            'sha256':  64, 'SHA256':  64,
-            'sha384': 128, 'SHA384': 128,
-            'sha512': 128, 'SHA512': 128,
-            }.get(self.name, 0)
-        return self._block_size
 
 W_Hash.typedef = TypeDef(
     'HASH',
@@ -142,11 +115,11 @@
     digestsize=GetSetProperty(W_Hash.get_digest_size),
     block_size=GetSetProperty(W_Hash.get_block_size),
     )
+W_Hash.acceptable_as_base_class = False
 
 @unwrap_spec(name=str, string='bufferstr')
 def new(space, name, string=''):
     w_hash = W_Hash(space, name)
-    w_hash.initdigest(space, name)
     w_hash.update(space, string)
     return space.wrap(w_hash)
 
@@ -158,6 +131,6 @@
         return new(space, name, string)
     return new_hash
 
-for name in algorithms:
-    newname = 'new_%s' % (name,)
-    globals()[newname] = make_new_hash(name, newname)
+for _name in algorithms:
+    _newname = 'new_%s' % (_name,)
+    globals()[_newname] = make_new_hash(_name, _newname)
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -110,6 +110,10 @@
         'struct GENERAL_NAME_st',
         [('type', rffi.INT),
          ])
+    EVP_MD_st = rffi_platform.Struct(
+        'EVP_MD',
+        [('md_size', rffi.INT),
+         ('block_size', rffi.INT)])
     EVP_MD_SIZE = rffi_platform.SizeOf('EVP_MD')
     EVP_MD_CTX_SIZE = rffi_platform.SizeOf('EVP_MD_CTX')
 
@@ -258,7 +262,7 @@
              [BIO, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP], X509)
 
 EVP_MD_CTX = rffi.COpaquePtr('EVP_MD_CTX', compilation_info=eci)
-EVP_MD     = rffi.COpaquePtr('EVP_MD', compilation_info=eci)
+EVP_MD     = lltype.Ptr(EVP_MD_st)
 
 OpenSSL_add_all_digests = external(
     'OpenSSL_add_all_digests', [], lltype.Void)


More information about the pypy-commit mailing list