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*.
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 7c49aff..a8e95a2 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -1007,6 +1007,7 @@
 	char *ptr;
 	Py_ssize_t ntodo;
 	Py_ssize_t ndone, nnow;
+	Py_buffer pbuf;
 
 	if (f->f_fp == NULL)
 		return err_closed();
@@ -1015,8 +1016,10 @@
 	    (f->f_bufend - f->f_bufptr) > 0 &&
 	    f->f_buf[0] != '\0')
 		return err_iterbuffered();
-	if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo))
+	if (!PyArg_ParseTuple(args, "w*", &pbuf))
 		return NULL;
+	ptr = pbuf.buf;
+	ntodo = pbuf.len;
 	ndone = 0;
 	while (ntodo > 0) {
 		FILE_BEGIN_ALLOW_THREADS(f)
@@ -1029,11 +1032,13 @@
 				break;
 			PyErr_SetFromErrno(PyExc_IOError);
 			clearerr(f->f_fp);
+			PyBuffer_Release(&pbuf);
 			return NULL;
 		}
 		ndone += nnow;
 		ntodo -= nnow;
 	}
+	PyBuffer_Release(&pbuf);
 	return PyInt_FromSsize_t(ndone);
 }
 
@@ -1611,17 +1616,26 @@
 static PyObject *
 file_write(PyFileObject *f, PyObject *args)
 {
+	Py_buffer pbuf;
 	char *s;
 	Py_ssize_t n, n2;
 	if (f->f_fp == NULL)
 		return err_closed();
-	if (!PyArg_ParseTuple(args, f->f_binary ? "s#" : "t#", &s, &n))
+	if (f->f_binary) {
+		if (!PyArg_ParseTuple(args, "s*", &pbuf))
+			return NULL;
+		s = pbuf.buf;
+		n = pbuf.len;
+	} else
+		if (!PyArg_ParseTuple(args, "t#", &s, &n))
 		return NULL;
 	f->f_softspace = 0;
 	FILE_BEGIN_ALLOW_THREADS(f)
 	errno = 0;
 	n2 = fwrite(s, 1, n, f->f_fp);
 	FILE_END_ALLOW_THREADS(f)
+	if (f->f_binary)
+		PyBuffer_Release(&pbuf);
 	if (n2 != n) {
 		PyErr_SetFromErrno(PyExc_IOError);
 		clearerr(f->f_fp);