diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2008-08-13 15:53:07 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2008-08-13 15:53:07 (GMT) |
commit | 423be95dcf55b0b8737207beb7b30eb549430dba (patch) | |
tree | b23453f2dc43d809aca931203a9580a81bd938fe /Python | |
parent | 688356f59f3b0fe2412a5f66b79f0f9fdc4a98d2 (diff) | |
download | cpython-423be95dcf55b0b8737207beb7b30eb549430dba.zip cpython-423be95dcf55b0b8737207beb7b30eb549430dba.tar.gz cpython-423be95dcf55b0b8737207beb7b30eb549430dba.tar.bz2 |
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*.
........
Diffstat (limited to 'Python')
-rw-r--r-- | Python/getargs.c | 119 | ||||
-rw-r--r-- | Python/marshal.c | 6 |
2 files changed, 113 insertions, 12 deletions
diff --git a/Python/getargs.c b/Python/getargs.c index 36a6261..cf4444c 100644 --- a/Python/getargs.c +++ b/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; } diff --git a/Python/marshal.c b/Python/marshal.c index e7e4154..d3f2d7f 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -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; } |