152 lines
4.6 KiB
Diff
152 lines
4.6 KiB
Diff
|
Index: Lib/test/test_hashlib.py
|
||
|
================================================================================
|
||
|
--- Lib/test/test_hashlib.py
|
||
|
+++ Lib/test/test_hashlib.py
|
||
|
@@ -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()
|
||
|
@@ -74,7 +73,22 @@
|
||
|
def test_case_md5_2(self):
|
||
|
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
|
||
|
--- Modules/_hashopenssl.c
|
||
|
+++ Modules/_hashopenssl.c
|
||
|
@@ -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 */
|