Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9406f5c

Browse files
committed
Use the new buffer api for input data.
1 parent 6777c85 commit 9406f5c

2 files changed

Lines changed: 80 additions & 28 deletions

File tree

Lib/hashlib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# $Id$
22
#
3-
# Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
3+
# Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
44
# Licensed to PSF under a Contributor Agreement.
55
#
66

Modules/_hashopenssl.c

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* Module that wraps all OpenSSL hash algorithms */
22

33
/*
4-
* Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
4+
* Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
55
* Licensed to PSF under a Contributor Agreement.
66
*
77
* Derived from a skeleton of shamodule.c containing work performed by:
@@ -28,6 +28,11 @@ typedef struct {
2828
PyObject_HEAD
2929
PyObject *name; /* name of this hash algorithm */
3030
EVP_MD_CTX ctx; /* OpenSSL message digest context */
31+
/*
32+
* TODO investigate performance impact of including a lock for this object
33+
* here and releasing the Python GIL while hash updates are in progress.
34+
* (perhaps only release GIL if input length will take long to process?)
35+
*/
3136
} EVPobject;
3237

3338

@@ -147,20 +152,41 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
147152
return retval;
148153
}
149154

155+
#define MY_GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) do { \
156+
if (!PyObject_CheckBuffer((obj))) { \
157+
PyErr_SetString(PyExc_TypeError, \
158+
"object supporting the buffer API required"); \
159+
return NULL; \
160+
} \
161+
if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
162+
return NULL; \
163+
} \
164+
if ((viewp)->ndim > 1) { \
165+
PyErr_SetString(PyExc_BufferError, \
166+
"Buffer must be single dimension"); \
167+
PyObject_ReleaseBuffer((obj), (viewp)); \
168+
return NULL; \
169+
} \
170+
} while(0);
171+
150172
PyDoc_STRVAR(EVP_update__doc__,
151173
"Update this hash object's state with the provided string.");
152174

153175
static PyObject *
154176
EVP_update(EVPobject *self, PyObject *args)
155177
{
156-
unsigned char *cp;
157-
Py_ssize_t len;
178+
PyObject *obj;
179+
PyBuffer view;
158180

159-
if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
181+
if (!PyArg_ParseTuple(args, "O:update", &obj))
160182
return NULL;
161183

162-
EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
163-
unsigned int));
184+
MY_GET_BUFFER_VIEW_OR_ERROUT(obj, &view);
185+
186+
EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
187+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
188+
189+
PyObject_ReleaseBuffer(obj, &view);
164190

165191
Py_INCREF(Py_None);
166192
return Py_None;
@@ -225,34 +251,43 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
225251
{
226252
static char *kwlist[] = {"name", "string", NULL};
227253
PyObject *name_obj = NULL;
254+
PyObject *data_obj = NULL;
255+
PyBuffer view;
228256
char *nameStr;
229-
unsigned char *cp = NULL;
230-
Py_ssize_t len = 0;
231257
const EVP_MD *digest;
232258

233-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s#:HASH", kwlist,
234-
&name_obj, &cp, &len)) {
259+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist,
260+
&name_obj, &data_obj)) {
235261
return -1;
236262
}
237263

264+
if (data_obj)
265+
MY_GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
266+
238267
if (!PyArg_Parse(name_obj, "s", &nameStr)) {
239268
PyErr_SetString(PyExc_TypeError, "name must be a string");
269+
if (data_obj)
270+
PyObject_ReleaseBuffer(data_obj, &view);
240271
return -1;
241272
}
242273

243274
digest = EVP_get_digestbyname(nameStr);
244275
if (!digest) {
245276
PyErr_SetString(PyExc_ValueError, "unknown hash function");
277+
if (data_obj)
278+
PyObject_ReleaseBuffer(data_obj, &view);
246279
return -1;
247280
}
248281
EVP_DigestInit(&self->ctx, digest);
249282

250283
self->name = name_obj;
251284
Py_INCREF(self->name);
252285

253-
if (cp && len)
254-
EVP_DigestUpdate(&self->ctx, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
255-
unsigned int));
286+
if (data_obj) {
287+
EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf,
288+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
289+
PyObject_ReleaseBuffer(data_obj, &view);
290+
}
256291

257292
return 0;
258293
}
@@ -361,13 +396,14 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
361396
{
362397
static char *kwlist[] = {"name", "string", NULL};
363398
PyObject *name_obj = NULL;
399+
PyObject *data_obj = NULL;
400+
PyBuffer view = { 0 };
401+
PyObject *ret_obj;
364402
char *name;
365403
const EVP_MD *digest;
366-
unsigned char *cp = NULL;
367-
Py_ssize_t len = 0;
368404

369-
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s#:new", kwlist,
370-
&name_obj, &cp, &len)) {
405+
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
406+
&name_obj, &data_obj)) {
371407
return NULL;
372408
}
373409

@@ -376,10 +412,17 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
376412
return NULL;
377413
}
378414

415+
if (data_obj)
416+
MY_GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
417+
379418
digest = EVP_get_digestbyname(name);
380419

381-
return EVPnew(name_obj, digest, NULL, cp, Py_SAFE_DOWNCAST(len, Py_ssize_t,
382-
unsigned int));
420+
ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf,
421+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int));
422+
423+
if (data_obj)
424+
PyObject_ReleaseBuffer(data_obj, &view);
425+
return ret_obj;
383426
}
384427

385428
/*
@@ -393,18 +436,27 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
393436
static PyObject * \
394437
EVP_new_ ## NAME (PyObject *self, PyObject *args) \
395438
{ \
396-
unsigned char *cp = NULL; \
397-
Py_ssize_t len = 0; \
439+
PyObject *data_obj = NULL; \
440+
PyBuffer view = { 0 }; \
441+
PyObject *ret_obj; \
398442
\
399-
if (!PyArg_ParseTuple(args, "|s#:" #NAME , &cp, &len)) { \
443+
if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
400444
return NULL; \
401445
} \
402446
\
403-
return EVPnew( \
404-
CONST_ ## NAME ## _name_obj, \
405-
NULL, \
406-
CONST_new_ ## NAME ## _ctx_p, \
407-
cp, Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int)); \
447+
if (data_obj) \
448+
MY_GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
449+
\
450+
ret_obj = EVPnew( \
451+
CONST_ ## NAME ## _name_obj, \
452+
NULL, \
453+
CONST_new_ ## NAME ## _ctx_p, \
454+
(unsigned char*)view.buf, \
455+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
456+
\
457+
if (data_obj) \
458+
PyObject_ReleaseBuffer(data_obj, &view); \
459+
return ret_obj; \
408460
}
409461

410462
/* a PyMethodDef structure for the constructor */

0 commit comments

Comments
 (0)