[Python-checkins] r69561 - in python/trunk: Lib/test/test_hashlib.py Misc/NEWS Modules/_hashopenssl.c Modules/hashlib.h Modules/md5.c Modules/md5.h Modules/md5module.c Modules/sha256module.c Modules/sha512module.c Modules/shamodule.c
gregory.p.smith
python-checkins at python.org
Fri Feb 13 04:00:01 CET 2009
Author: gregory.p.smith
Date: Fri Feb 13 04:00:00 2009
New Revision: 69561
Log:
- Issue #3745: Fix hashlib to always reject unicode and non buffer-api
supporting objects as input no matter how it was compiled (built in
implementations or external openssl library).
(backported from a py3k branch)
Added:
python/trunk/Modules/hashlib.h
Modified:
python/trunk/Lib/test/test_hashlib.py
python/trunk/Misc/NEWS
python/trunk/Modules/_hashopenssl.c
python/trunk/Modules/md5.c
python/trunk/Modules/md5.h
python/trunk/Modules/md5module.c
python/trunk/Modules/sha256module.c
python/trunk/Modules/sha512module.c
python/trunk/Modules/shamodule.c
Modified: python/trunk/Lib/test/test_hashlib.py
==============================================================================
--- python/trunk/Lib/test/test_hashlib.py (original)
+++ python/trunk/Lib/test/test_hashlib.py Fri Feb 13 04:00:00 2009
@@ -39,11 +39,11 @@
h = hashlib.new(name)
self.assert_(hexstr(h.digest()) == h.hexdigest())
-
def test_large_update(self):
aas = 'a' * 128
bees = 'b' * 127
cees = 'c' * 126
+ abcs = aas + bees + cees
for name in self.supported_hash_names:
m1 = hashlib.new(name)
@@ -52,8 +52,11 @@
m1.update(cees)
m2 = hashlib.new(name)
- m2.update(aas + bees + cees)
- self.assertEqual(m1.digest(), m2.digest())
+ m2.update(abcs)
+ self.assertEqual(m1.digest(), m2.digest(), name+' update problem.')
+
+ m3 = hashlib.new(name, abcs)
+ self.assertEqual(m1.digest(), m3.digest(), name+' new problem.')
def check(self, name, data, digest):
# test the direct constructors
@@ -63,6 +66,18 @@
computed = hashlib.new(name, data).hexdigest()
self.assert_(computed == digest)
+ def check_no_unicode(self, algorithm_name):
+ # Unicode objects are not allowed as input.
+ self.assertRaises(TypeError, getattr(hashlib, algorithm_name), u'spam')
+ self.assertRaises(TypeError, hashlib.new, algorithm_name, u'spam')
+
+ def test_no_unicode(self):
+ self.check_no_unicode('md5')
+ self.check_no_unicode('sha1')
+ self.check_no_unicode('sha224')
+ self.check_no_unicode('sha256')
+ self.check_no_unicode('sha384')
+ self.check_no_unicode('sha512')
def test_case_md5_0(self):
self.check('md5', '', 'd41d8cd98f00b204e9800998ecf8427e')
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Fri Feb 13 04:00:00 2009
@@ -508,6 +508,10 @@
Extension Modules
-----------------
+- Issue #3745: Fix hashlib to always reject unicode and non buffer-api
+ supporting objects as input no matter how it was compiled (built in
+ implementations or external openssl library).
+
- Issue #4397: Fix occasional test_socket failure on OS X.
- Issue #4279: Fix build of parsermodule under Cygwin.
Modified: python/trunk/Modules/_hashopenssl.c
==============================================================================
--- python/trunk/Modules/_hashopenssl.c (original)
+++ python/trunk/Modules/_hashopenssl.c Fri Feb 13 04:00:00 2009
@@ -1,7 +1,7 @@
/* Module that wraps all OpenSSL hash algorithms */
/*
- * Copyright (C) 2005 Gregory P. Smith (greg at krypto.org)
+ * Copyright (C) 2005-2007 Gregory P. Smith (greg at krypto.org)
* Licensed to PSF under a Contributor Agreement.
*
* Derived from a skeleton of shamodule.c containing work performed by:
@@ -15,6 +15,7 @@
#include "Python.h"
#include "structmember.h"
+#include "hashlib.h"
/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
@@ -30,6 +31,11 @@
PyObject_HEAD
PyObject *name; /* name of this hash algorithm */
EVP_MD_CTX ctx; /* OpenSSL message digest context */
+ /*
+ * TODO investigate performance impact of including a lock for this object
+ * here and releasing the Python GIL while hash updates are in progress.
+ * (perhaps only release GIL if input length will take long to process?)
+ */
} EVPobject;
@@ -160,24 +166,30 @@
static PyObject *
EVP_update(EVPobject *self, PyObject *args)
{
- unsigned char *cp;
- Py_ssize_t len;
+ PyObject *obj;
+ Py_buffer view;
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ if (!PyArg_ParseTuple(args, "O:update", &obj))
return NULL;
- if (len > 0 && len <= MUNCH_SIZE) {
- EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
- unsigned int));
+ GET_BUFFER_VIEW_OR_ERROUT(obj, &view, NULL);
+
+ if (view.len > 0 && view.len <= MUNCH_SIZE) {
+ EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
} else {
- Py_ssize_t offset = 0;
- while (len) {
+ Py_ssize_t len = view.len;
+ unsigned char *cp = (unsigned char *)view.buf;
+ while (len > 0) {
unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
- EVP_DigestUpdate(&self->ctx, cp + offset, process);
+ EVP_DigestUpdate(&self->ctx, cp, process);
len -= process;
- offset += process;
+ cp += process;
}
}
+
+ PyBuffer_Release(&view);
+
Py_INCREF(Py_None);
return Py_None;
}
@@ -241,24 +253,31 @@
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
+ PyObject *data_obj = NULL;
+ Py_buffer view;
char *nameStr;
- unsigned char *cp = NULL;
- Py_ssize_t len = 0;
const EVP_MD *digest;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s#:HASH", kwlist,
- &name_obj, &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist,
+ &name_obj, &data_obj)) {
return -1;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, -1);
+
if (!PyArg_Parse(name_obj, "s", &nameStr)) {
PyErr_SetString(PyExc_TypeError, "name must be a string");
+ if (data_obj)
+ PyBuffer_Release(&view);
return -1;
}
digest = EVP_get_digestbyname(nameStr);
if (!digest) {
PyErr_SetString(PyExc_ValueError, "unknown hash function");
+ if (data_obj)
+ PyBuffer_Release(&view);
return -1;
}
EVP_DigestInit(&self->ctx, digest);
@@ -266,21 +285,23 @@
self->name = name_obj;
Py_INCREF(self->name);
- if (cp && len) {
- if (len > 0 && len <= MUNCH_SIZE) {
- EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
- unsigned int));
+ if (data_obj) {
+ if (view.len > 0 && view.len <= MUNCH_SIZE) {
+ EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
} else {
- Py_ssize_t offset = 0;
- while (len) {
+ Py_ssize_t len = view.len;
+ unsigned char *cp = (unsigned char*)view.buf;
+ while (len > 0) {
unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
- EVP_DigestUpdate(&self->ctx, cp + offset, process);
+ EVP_DigestUpdate(&self->ctx, cp, process);
len -= process;
- offset += process;
+ cp += process;
}
}
+ PyBuffer_Release(&view);
}
-
+
return 0;
}
#endif
@@ -373,7 +394,7 @@
unsigned int));
} else {
Py_ssize_t offset = 0;
- while (len) {
+ while (len > 0) {
unsigned int process = len > MUNCH_SIZE ? MUNCH_SIZE : len;
EVP_DigestUpdate(&self->ctx, cp + offset, process);
len -= process;
@@ -400,13 +421,14 @@
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
+ PyObject *data_obj = NULL;
+ Py_buffer view = { 0 };
+ PyObject *ret_obj;
char *name;
const EVP_MD *digest;
- unsigned char *cp = NULL;
- Py_ssize_t len = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s#:new", kwlist,
- &name_obj, &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
+ &name_obj, &data_obj)) {
return NULL;
}
@@ -415,9 +437,17 @@
return NULL;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL);
+
digest = EVP_get_digestbyname(name);
- return EVPnew(name_obj, digest, NULL, cp, len);
+ ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
+
+ if (data_obj)
+ PyBuffer_Release(&view);
+ return ret_obj;
}
/*
@@ -431,18 +461,27 @@
static PyObject * \
EVP_new_ ## NAME (PyObject *self, PyObject *args) \
{ \
- unsigned char *cp = NULL; \
- Py_ssize_t len = 0; \
+ PyObject *data_obj = NULL; \
+ Py_buffer view = { 0 }; \
+ PyObject *ret_obj; \
\
- if (!PyArg_ParseTuple(args, "|s#:" #NAME , &cp, &len)) { \
+ if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
return NULL; \
} \
\
- return EVPnew( \
- CONST_ ## NAME ## _name_obj, \
- NULL, \
- CONST_new_ ## NAME ## _ctx_p, \
- cp, len); \
+ if (data_obj) \
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL); \
+ \
+ ret_obj = EVPnew( \
+ CONST_ ## NAME ## _name_obj, \
+ NULL, \
+ CONST_new_ ## NAME ## _ctx_p, \
+ (unsigned char*)view.buf, \
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
+ \
+ if (data_obj) \
+ PyBuffer_Release(&view); \
+ return ret_obj; \
}
/* a PyMethodDef structure for the constructor */
Added: python/trunk/Modules/hashlib.h
==============================================================================
--- (empty file)
+++ python/trunk/Modules/hashlib.h Fri Feb 13 04:00:00 2009
@@ -0,0 +1,28 @@
+/* Common code for use by all hashlib related modules. */
+
+/*
+ * Given a PyObject* obj, fill in the Py_buffer* viewp with the result
+ * of PyObject_GetBuffer. Sets and exception and issues a returns
+ * on any errors.
+ */
+#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp, error_return) do { \
+ if (PyUnicode_Check((obj))) { \
+ PyErr_SetString(PyExc_TypeError, \
+ "Unicode-objects must be encoded before hashing");\
+ return error_return; \
+ } \
+ if (!PyObject_CheckBuffer((obj))) { \
+ PyErr_SetString(PyExc_TypeError, \
+ "object supporting the buffer API required"); \
+ return error_return; \
+ } \
+ if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
+ return error_return; \
+ } \
+ if ((viewp)->ndim > 1) { \
+ PyErr_SetString(PyExc_BufferError, \
+ "Buffer must be single dimension"); \
+ PyBuffer_Release((viewp)); \
+ return error_return; \
+ } \
+ } while(0);
Modified: python/trunk/Modules/md5.c
==============================================================================
--- python/trunk/Modules/md5.c (original)
+++ python/trunk/Modules/md5.c Fri Feb 13 04:00:00 2009
@@ -321,10 +321,10 @@
}
void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned int nbytes)
{
const md5_byte_t *p = data;
- int left = nbytes;
+ unsigned int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
@@ -333,7 +333,7 @@
/* this special case is handled recursively */
if (nbytes > INT_MAX - offset) {
- int overlap;
+ unsigned int overlap;
/* handle the append in two steps to prevent overflow */
overlap = 64 - offset;
@@ -351,7 +351,7 @@
/* Process an initial partial block. */
if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+ unsigned int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
Modified: python/trunk/Modules/md5.h
==============================================================================
--- python/trunk/Modules/md5.h (original)
+++ python/trunk/Modules/md5.h Fri Feb 13 04:00:00 2009
@@ -79,7 +79,7 @@
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+void md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
Modified: python/trunk/Modules/md5module.c
==============================================================================
--- python/trunk/Modules/md5module.c (original)
+++ python/trunk/Modules/md5module.c Fri Feb 13 04:00:00 2009
@@ -12,6 +12,7 @@
#include "Python.h"
#include "structmember.h"
#include "md5.h"
+#include "hashlib.h"
typedef struct {
PyObject_HEAD
@@ -50,14 +51,18 @@
static PyObject *
md5_update(md5object *self, PyObject *args)
{
- unsigned char *cp;
- int len;
+ PyObject *data_obj;
+ Py_buffer view;
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ if (!PyArg_ParseTuple(args, "O:update", &data_obj))
return NULL;
- md5_append(&self->md5, cp, len);
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL);
+ md5_append(&self->md5, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
+
+ PyBuffer_Release(&view);
Py_INCREF(Py_None);
return Py_None;
}
@@ -261,18 +266,25 @@
MD5_new(PyObject *self, PyObject *args)
{
md5object *md5p;
- unsigned char *cp = NULL;
- int len = 0;
+ PyObject *data_obj = NULL;
+ Py_buffer view;
- if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
+ if (!PyArg_ParseTuple(args, "|O:new", &data_obj))
return NULL;
- if ((md5p = newmd5object()) == NULL)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL);
+
+ if ((md5p = newmd5object()) == NULL) {
+ PyBuffer_Release(&view);
return NULL;
+ }
- if (cp)
- md5_append(&md5p->md5, cp, len);
+ if (data_obj) {
+ md5_append(&md5p->md5, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
+ }
+ PyBuffer_Release(&view);
return (PyObject *)md5p;
}
Modified: python/trunk/Modules/sha256module.c
==============================================================================
--- python/trunk/Modules/sha256module.c (original)
+++ python/trunk/Modules/sha256module.c Fri Feb 13 04:00:00 2009
@@ -18,6 +18,7 @@
#include "Python.h"
#include "structmember.h"
+#include "hashlib.h"
/* Endianness testing and definitions */
@@ -480,14 +481,17 @@
static PyObject *
SHA256_update(SHAobject *self, PyObject *args)
{
- unsigned char *cp;
- int len;
+ PyObject *obj;
+ Py_buffer buf;
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ if (!PyArg_ParseTuple(args, "O:update", &obj))
return NULL;
- sha_update(self, cp, len);
+ GET_BUFFER_VIEW_OR_ERROUT(obj, &buf, NULL);
+ sha_update(self, buf.buf, buf.len);
+
+ PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
@@ -614,14 +618,17 @@
{
static char *kwlist[] = {"string", NULL};
SHAobject *new;
- unsigned char *cp = NULL;
- int len;
+ PyObject *data_obj = NULL;
+ Py_buffer buf;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist,
+ &data_obj)) {
return NULL;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL);
+
if ((new = newSHA256object()) == NULL)
return NULL;
@@ -631,8 +638,10 @@
Py_DECREF(new);
return NULL;
}
- if (cp)
- sha_update(new, cp, len);
+ if (data_obj) {
+ sha_update(new, buf.buf, buf.len);
+ PyBuffer_Release(&buf);
+ }
return (PyObject *)new;
}
@@ -645,14 +654,17 @@
{
static char *kwlist[] = {"string", NULL};
SHAobject *new;
- unsigned char *cp = NULL;
- int len;
+ PyObject *data_obj = NULL;
+ Py_buffer buf;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist,
+ &data_obj)) {
return NULL;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL);
+
if ((new = newSHA224object()) == NULL)
return NULL;
@@ -662,8 +674,10 @@
Py_DECREF(new);
return NULL;
}
- if (cp)
- sha_update(new, cp, len);
+ if (data_obj) {
+ sha_update(new, buf.buf, buf.len);
+ PyBuffer_Release(&buf);
+ }
return (PyObject *)new;
}
Modified: python/trunk/Modules/sha512module.c
==============================================================================
--- python/trunk/Modules/sha512module.c (original)
+++ python/trunk/Modules/sha512module.c Fri Feb 13 04:00:00 2009
@@ -18,6 +18,7 @@
#include "Python.h"
#include "structmember.h"
+#include "hashlib.h"
#ifdef PY_LONG_LONG /* If no PY_LONG_LONG, don't compile anything! */
@@ -546,14 +547,17 @@
static PyObject *
SHA512_update(SHAobject *self, PyObject *args)
{
- unsigned char *cp;
- int len;
+ PyObject *obj;
+ Py_buffer buf;
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ if (!PyArg_ParseTuple(args, "O:update", &obj))
return NULL;
- sha512_update(self, cp, len);
+ GET_BUFFER_VIEW_OR_ERROUT(obj, &buf, NULL);
+ sha512_update(self, buf.buf, buf.len);
+
+ PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
@@ -680,14 +684,17 @@
{
static char *kwlist[] = {"string", NULL};
SHAobject *new;
- unsigned char *cp = NULL;
- int len;
+ PyObject *data_obj = NULL;
+ Py_buffer buf;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist,
+ &data_obj)) {
return NULL;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL);
+
if ((new = newSHA512object()) == NULL)
return NULL;
@@ -697,8 +704,10 @@
Py_DECREF(new);
return NULL;
}
- if (cp)
- sha512_update(new, cp, len);
+ if (data_obj) {
+ sha512_update(new, buf.buf, buf.len);
+ PyBuffer_Release(&buf);
+ }
return (PyObject *)new;
}
@@ -711,14 +720,17 @@
{
static char *kwlist[] = {"string", NULL};
SHAobject *new;
- unsigned char *cp = NULL;
- int len;
+ PyObject *data_obj = NULL;
+ Py_buffer buf;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist,
+ &data_obj)) {
return NULL;
}
+ if (data_obj)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &buf, NULL);
+
if ((new = newSHA384object()) == NULL)
return NULL;
@@ -728,8 +740,10 @@
Py_DECREF(new);
return NULL;
}
- if (cp)
- sha512_update(new, cp, len);
+ if (data_obj) {
+ sha512_update(new, buf.buf, buf.len);
+ PyBuffer_Release(&buf);
+ }
return (PyObject *)new;
}
Modified: python/trunk/Modules/shamodule.c
==============================================================================
--- python/trunk/Modules/shamodule.c (original)
+++ python/trunk/Modules/shamodule.c Fri Feb 13 04:00:00 2009
@@ -17,6 +17,7 @@
#include "Python.h"
#include "structmember.h"
+#include "hashlib.h"
/* Endianness testing and definitions */
@@ -236,9 +237,9 @@
/* update the SHA digest */
static void
-sha_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
+sha_update(SHAobject *sha_info, SHA_BYTE *buffer, unsigned int count)
{
- int i;
+ unsigned int i;
SHA_INT32 clo;
clo = sha_info->count_lo + ((SHA_INT32) count << 3);
@@ -428,14 +429,18 @@
static PyObject *
SHA_update(SHAobject *self, PyObject *args)
{
- unsigned char *cp;
- int len;
+ PyObject *data_obj;
+ Py_buffer view;
- if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ if (!PyArg_ParseTuple(args, "O:update", &data_obj))
return NULL;
- sha_update(self, cp, len);
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL);
+
+ sha_update(self, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
+ PyBuffer_Release(&view);
Py_INCREF(Py_None);
return Py_None;
}
@@ -535,26 +540,34 @@
{
static char *kwlist[] = {"string", NULL};
SHAobject *new;
- unsigned char *cp = NULL;
- int len;
+ PyObject *data_obj = NULL;
+ Py_buffer view;
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
- &cp, &len)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|O:new", kwlist,
+ &data_obj)) {
return NULL;
}
- if ((new = newSHAobject()) == NULL)
+ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view, NULL);
+
+ if ((new = newSHAobject()) == NULL) {
+ PyBuffer_Release(&view);
return NULL;
+ }
sha_init(new);
if (PyErr_Occurred()) {
Py_DECREF(new);
+ PyBuffer_Release(&view);
return NULL;
}
- if (cp)
- sha_update(new, cp, len);
+ if (data_obj) {
+ sha_update(new, (unsigned char*)view.buf,
+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
+ }
+ PyBuffer_Release(&view);
return (PyObject *)new;
}
More information about the Python-checkins
mailing list