]> granicus.if.org Git - python/commitdiff
backport r66496: integer overflow in _hashopenssl #3886
authorBenjamin Peterson <benjamin@python.org>
Thu, 18 Sep 2008 01:27:26 +0000 (01:27 +0000)
committerBenjamin Peterson <benjamin@python.org>
Thu, 18 Sep 2008 01:27:26 +0000 (01:27 +0000)
Lib/test/test_hashlib.py
Misc/NEWS
Modules/_hashopenssl.c

index 1dcadcda6112dd3f38ff2e54410b4f50ae25c740..5894ddd4bac7c2d41f0ae624aca16fcfe7caa6af 100644 (file)
@@ -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 @@ class HashLibTestCase(unittest.TestCase):
             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 @@ class HashLibTestCase(unittest.TestCase):
         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
index e0e950878802b4b00ab2f5df62a48eeb73ea7dcd..cba0d06fe2ea7930dd595062618ed5992d309947 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -173,6 +173,9 @@ Library
 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.
 
index 859644fc70d28f422dca38a92313b3a1bd09dcd7..f928c3c149a9062b587eb8a60e6bf8cf6361fb67 100644 (file)
@@ -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 @@ EVP_update(EVPobject *self, PyObject *args)
     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 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
     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 PyTypeObject EVPtype = {
 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 @@ EVPnew(PyObject *name_obj,
         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 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
 
     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 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
                 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 */