mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
Merged revisions 65654 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r65654 | martin.v.loewis | 2008-08-12 16:49:50 +0200 (Tue, 12 Aug 2008) | 6 lines Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple, by denying s# to parse objects that have a releasebuffer procedure, and introducing s*. More module might need to get converted to use s*. ........
This commit is contained in:
parent
688356f59f
commit
423be95dcf
32 changed files with 721 additions and 390 deletions
119
Python/getargs.c
119
Python/getargs.c
|
@ -44,6 +44,7 @@ static char *converttuple(PyObject *, const char **, va_list *, int,
|
|||
static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
|
||||
size_t, PyObject **);
|
||||
static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
|
||||
static int getbuffer(PyObject *, Py_buffer *, char**);
|
||||
|
||||
static int vgetargskeywords(PyObject *, PyObject *,
|
||||
const char *, char **, va_list *, int);
|
||||
|
@ -789,7 +790,25 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
need to be cleaned up! */
|
||||
|
||||
case 's': {/* text string */
|
||||
if (*format == '#') {
|
||||
if (*format == '*') {
|
||||
Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
|
||||
|
||||
if (PyUnicode_Check(arg)) {
|
||||
uarg = UNICODE_DEFAULT_ENCODING(arg);
|
||||
if (uarg == NULL)
|
||||
return converterr(CONV_UNICODE,
|
||||
arg, msgbuf, bufsize);
|
||||
PyBuffer_FillInfo(p, arg,
|
||||
PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg),
|
||||
1, 0);
|
||||
}
|
||||
else { /* any buffer-like object */
|
||||
char *buf;
|
||||
if (getbuffer(arg, p, &buf) < 0)
|
||||
return converterr(buf, arg, msgbuf, bufsize);
|
||||
}
|
||||
format++;
|
||||
} else if (*format == '#') {
|
||||
void **p = (void **)va_arg(*p_va, char **);
|
||||
FETCH_SIZE;
|
||||
|
||||
|
@ -832,10 +851,17 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
case 'y': {/* any buffer-like object, but not PyUnicode */
|
||||
void **p = (void **)va_arg(*p_va, char **);
|
||||
char *buf;
|
||||
Py_ssize_t count = convertbuffer(arg, p, &buf);
|
||||
Py_ssize_t count;
|
||||
if (*format == '*') {
|
||||
if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)
|
||||
return converterr(buf, arg, msgbuf, bufsize);
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
count = convertbuffer(arg, p, &buf);
|
||||
if (count < 0)
|
||||
return converterr(buf, arg, msgbuf, bufsize);
|
||||
if (*format == '#') {
|
||||
else if (*format == '#') {
|
||||
FETCH_SIZE;
|
||||
STORE_SIZE(count);
|
||||
format++;
|
||||
|
@ -844,7 +870,27 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
}
|
||||
|
||||
case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */
|
||||
if (*format == '#') { /* any buffer-like object */
|
||||
if (*format == '*') {
|
||||
Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);
|
||||
|
||||
if (arg == Py_None)
|
||||
PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);
|
||||
else if (PyUnicode_Check(arg)) {
|
||||
uarg = UNICODE_DEFAULT_ENCODING(arg);
|
||||
if (uarg == NULL)
|
||||
return converterr(CONV_UNICODE,
|
||||
arg, msgbuf, bufsize);
|
||||
PyBuffer_FillInfo(p, arg,
|
||||
PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg),
|
||||
1, 0);
|
||||
}
|
||||
else { /* any buffer-like object */
|
||||
char *buf;
|
||||
if (getbuffer(arg, p, &buf) < 0)
|
||||
return converterr(buf, arg, msgbuf, bufsize);
|
||||
}
|
||||
format++;
|
||||
} else if (*format == '#') { /* any buffer-like object */
|
||||
void **p = (void **)va_arg(*p_va, char **);
|
||||
FETCH_SIZE;
|
||||
|
||||
|
@ -1189,6 +1235,26 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
int temp=-1;
|
||||
Py_buffer view;
|
||||
|
||||
if (pb && pb->bf_releasebuffer && *format != '*')
|
||||
/* Buffer must be released, yet caller does not use
|
||||
the Py_buffer protocol. */
|
||||
return converterr("pinned buffer", arg, msgbuf, bufsize);
|
||||
|
||||
|
||||
if (pb && pb->bf_getbuffer && *format == '*') {
|
||||
/* Caller is interested in Py_buffer, and the object
|
||||
supports it directly. */
|
||||
format++;
|
||||
if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {
|
||||
PyErr_Clear();
|
||||
return converterr("read-write buffer", arg, msgbuf, bufsize);
|
||||
}
|
||||
if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C'))
|
||||
return converterr("contiguous buffer", arg, msgbuf, bufsize);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Here we have processed w*, only w and w# remain. */
|
||||
if (pb == NULL ||
|
||||
pb->bf_getbuffer == NULL ||
|
||||
((temp = (*pb->bf_getbuffer)(arg, &view,
|
||||
|
@ -1209,8 +1275,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
STORE_SIZE(count);
|
||||
format++;
|
||||
}
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(arg, &view);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1237,10 +1301,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
|
||||
count = view.len;
|
||||
*p = view.buf;
|
||||
/* XXX : shouldn't really release buffer, but it should be O.K.
|
||||
*/
|
||||
if (pb->bf_releasebuffer != NULL)
|
||||
(*pb->bf_releasebuffer)(arg, &view);
|
||||
if (pb->bf_releasebuffer)
|
||||
return converterr(
|
||||
"string or pinned buffer",
|
||||
arg, msgbuf, bufsize);
|
||||
|
||||
if (count < 0)
|
||||
return converterr("(unspecified)", arg, msgbuf, bufsize);
|
||||
{
|
||||
|
@ -1269,7 +1334,8 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
|
|||
*errmsg = NULL;
|
||||
*p = NULL;
|
||||
if (pb == NULL ||
|
||||
pb->bf_getbuffer == NULL) {
|
||||
pb->bf_getbuffer == NULL ||
|
||||
pb->bf_releasebuffer != NULL) {
|
||||
*errmsg = "bytes or read-only buffer";
|
||||
return -1;
|
||||
}
|
||||
|
@ -1285,6 +1351,35 @@ convertbuffer(PyObject *arg, void **p, char **errmsg)
|
|||
return count;
|
||||
}
|
||||
|
||||
/* XXX for 3.x, getbuffer and convertbuffer can probably
|
||||
be merged again. */
|
||||
static int
|
||||
getbuffer(PyObject *arg, Py_buffer *view, char**errmsg)
|
||||
{
|
||||
void *buf;
|
||||
Py_ssize_t count;
|
||||
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
|
||||
if (pb == NULL) {
|
||||
*errmsg = "string or buffer";
|
||||
return -1;
|
||||
}
|
||||
if (pb->bf_getbuffer) {
|
||||
if (pb->bf_getbuffer(arg, view, 0) < 0)
|
||||
return -1;
|
||||
if (!PyBuffer_IsContiguous(view, 'C')) {
|
||||
*errmsg = "contiguous buffer";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = convertbuffer(arg, &buf, errmsg);
|
||||
if (count < 0)
|
||||
return count;
|
||||
PyBuffer_FillInfo(view, NULL, buf, count, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Support for keyword arguments donated by
|
||||
Geoff Philbrick <philbric@delphi.hks.com> */
|
||||
|
||||
|
@ -1624,6 +1719,8 @@ skipitem(const char **p_format, va_list *p_va, int flags)
|
|||
else
|
||||
(void) va_arg(*p_va, int *);
|
||||
format++;
|
||||
} else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') {
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1168,11 +1168,14 @@ static PyObject *
|
|||
marshal_loads(PyObject *self, PyObject *args)
|
||||
{
|
||||
RFILE rf;
|
||||
Py_buffer p;
|
||||
char *s;
|
||||
Py_ssize_t n;
|
||||
PyObject* result;
|
||||
if (!PyArg_ParseTuple(args, "s#:loads", &s, &n))
|
||||
if (!PyArg_ParseTuple(args, "s*:loads", &p))
|
||||
return NULL;
|
||||
s = p.buf;
|
||||
n = p.len;
|
||||
rf.fp = NULL;
|
||||
rf.ptr = s;
|
||||
rf.end = s + n;
|
||||
|
@ -1180,6 +1183,7 @@ marshal_loads(PyObject *self, PyObject *args)
|
|||
rf.depth = 0;
|
||||
result = read_object(&rf);
|
||||
Py_DECREF(rf.strings);
|
||||
PyBuffer_Release(&p);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue