[Python-checkins] r66497 - in python/branches/release25-maint: Lib/test/test_hashlib.py Misc/NEWS Modules/_hashopenssl.c

benjamin.peterson python-checkins at python.org
Thu Sep 18 03:27:26 CEST 2008


Author: benjamin.peterson
Date: Thu Sep 18 03:27:26 2008
New Revision: 66497

Log:
backport r66496: integer overflow in _hashopenssl #3886

Modified:
   python/branches/release25-maint/Lib/test/test_hashlib.py
   python/branches/release25-maint/Misc/NEWS
   python/branches/release25-maint/Modules/_hashopenssl.c

Modified: python/branches/release25-maint/Lib/test/test_hashlib.py
==============================================================================
--- python/branches/release25-maint/Lib/test/test_hashlib.py	(original)
+++ python/branches/release25-maint/Lib/test/test_hashlib.py	Thu Sep 18 03:27:26 2008
@@ -9,7 +9,7 @@
 import hashlib
 import unittest
 from test import test_support
-
+from test.test_support import _4G, precisionbigmemtest
 
 def hexstr(s):
     import string
@@ -55,7 +55,6 @@
             m2.update(aas + bees + cees)
             self.assertEqual(m1.digest(), m2.digest())
 
-
     def check(self, name, data, digest):
         # test the direct constructors
         computed = getattr(hashlib, name)(data).hexdigest()
@@ -75,6 +74,21 @@
         self.check('md5', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
                    'd174ab98d277d9f5a5611c2c9f419d9f')
 
+    @precisionbigmemtest(size=_4G + 5, memuse=1)
+    def test_case_md5_huge(self, size):
+        if size == _4G + 5:
+            try:
+                self.check('md5', 'A'*size, 'c9af2dff37468ce5dfee8f2cfc0a9c6d')
+            except OverflowError:
+                pass # 32-bit arch
+
+    @precisionbigmemtest(size=_4G - 1, memuse=1)
+    def test_case_md5_uintmax(self, size):
+        if size == _4G - 1:
+            try:
+                self.check('md5', 'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3')
+            except OverflowError:
+                pass # 32-bit arch
 
     # use the three examples from Federal Information Processing Standards
     # Publication 180-1, Secure Hash Standard,  1995 April 17

Modified: python/branches/release25-maint/Misc/NEWS
==============================================================================
--- python/branches/release25-maint/Misc/NEWS	(original)
+++ python/branches/release25-maint/Misc/NEWS	Thu Sep 18 03:27:26 2008
@@ -173,6 +173,9 @@
 Extension Modules
 -----------------
 
+- Issue 3886: [CVE-2008-2316] Possible integer overflow in the _hashopenssl
+  module was closed.
+
 - Issue 1179: [CVE-2007-4965] Integer overflow in imageop module.
   Also fixes rgbimg module.
 

Modified: python/branches/release25-maint/Modules/_hashopenssl.c
==============================================================================
--- python/branches/release25-maint/Modules/_hashopenssl.c	(original)
+++ python/branches/release25-maint/Modules/_hashopenssl.c	Thu Sep 18 03:27:26 2008
@@ -19,6 +19,8 @@
 /* EVP is the preferred interface to hashing in OpenSSL */
 #include <openssl/evp.h>
 
+#define MUNCH_SIZE INT_MAX
+
 
 #ifndef HASH_OBJ_CONSTRUCTOR
 #define HASH_OBJ_CONSTRUCTOR 0
@@ -164,9 +166,18 @@
     if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
         return NULL;
 
+    if (len > 0 && len <= MUNCH_SIZE) {
     EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
                                                       unsigned int));
-
+    } else {
+        Py_ssize_t offset = 0;
+        while (len) {
+            unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
+            EVP_DigestUpdate(&self->ctx, cp + offset, process);
+            len -= process;
+            offset += process;
+        }
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -255,10 +266,21 @@
     self->name = name_obj;
     Py_INCREF(self->name);
 
-    if (cp && len)
+    if (cp && len) {
+        if (len > 0 && len <= MUNCH_SIZE) {
         EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
                                                           unsigned int));
-
+        } else {
+            Py_ssize_t offset = 0;
+            while (len) {
+                unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
+                EVP_DigestUpdate(&self->ctx, cp + offset, process);
+                len -= process;
+                offset += process;
+            }
+        }
+    }
+    
     return 0;
 }
 #endif
@@ -328,7 +350,7 @@
 static PyObject *
 EVPnew(PyObject *name_obj,
        const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
-       const unsigned char *cp, unsigned int len)
+       const unsigned char *cp, Py_ssize_t len)
 {
     EVPobject *self;
 
@@ -346,8 +368,20 @@
         EVP_DigestInit(&self->ctx, digest);
     }
 
-    if (cp && len)
-        EVP_DigestUpdate(&self->ctx, cp, len);
+    if (cp && len) {
+        if (len > 0 && len <= MUNCH_SIZE) {
+            EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
+                                                              unsigned int));
+        } else {
+            Py_ssize_t offset = 0;
+            while (len) {
+                unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
+                EVP_DigestUpdate(&self->ctx, cp + offset, process);
+                len -= process;
+                offset += process;
+            }
+        }
+    }
 
     return (PyObject *)self;
 }
@@ -384,8 +418,7 @@
 
     digest = EVP_get_digestbyname(name);
 
-    return EVPnew(name_obj, digest, NULL, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
-                                                               unsigned int));
+    return EVPnew(name_obj, digest, NULL, cp, len);
 }
 
 /*
@@ -410,7 +443,7 @@
                 CONST_ ## NAME ## _name_obj, \
                 NULL, \
                 CONST_new_ ## NAME ## _ctx_p, \
-                cp, Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int)); \
+                cp, len); \
     }
 
 /* a PyMethodDef structure for the constructor */


More information about the Python-checkins mailing list