summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/ctypes/test/test_frombuffer.py50
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_codecsmodule.c24
-rw-r--r--Modules/_ctypes/_ctypes.c57
-rw-r--r--Modules/_io/bytesio.c10
-rw-r--r--Modules/_sqlite/connection.c11
-rw-r--r--Modules/_sqlite/statement.c13
-rw-r--r--Modules/_struct.c23
-rw-r--r--Objects/abstract.c81
-rw-r--r--Objects/bytearrayobject.c92
-rw-r--r--Objects/bytes_methods.c33
-rw-r--r--Objects/bytesobject.c171
-rw-r--r--Objects/complexobject.c9
-rw-r--r--Objects/exceptions.c30
-rw-r--r--Objects/floatobject.c8
-rw-r--r--Objects/stringlib/join.h9
-rw-r--r--Python/bltinmodule.c34
17 files changed, 325 insertions, 333 deletions
diff --git a/Lib/ctypes/test/test_frombuffer.py b/Lib/ctypes/test/test_frombuffer.py
index ffb27a6ea3..6aa2d1c591 100644
--- a/Lib/ctypes/test/test_frombuffer.py
+++ b/Lib/ctypes/test/test_frombuffer.py
@@ -10,7 +10,7 @@ class X(Structure):
self._init_called = True
class Test(unittest.TestCase):
- def test_fom_buffer(self):
+ def test_from_buffer(self):
a = array.array("i", range(16))
x = (c_int * 16).from_buffer(a)
@@ -23,25 +23,37 @@ class Test(unittest.TestCase):
a[0], a[-1] = 200, -200
self.assertEqual(x[:], a.tolist())
- self.assertIn(a, x._objects.values())
+ self.assertRaises(BufferError, a.append, 100)
+ self.assertRaises(BufferError, a.pop)
- self.assertRaises(ValueError,
- c_int.from_buffer, a, -1)
+ del x; del y; gc.collect(); gc.collect(); gc.collect()
+ a.append(100)
+ a.pop()
+ x = (c_int * 16).from_buffer(a)
+
+ self.assertIn(a, [obj.obj if isinstance(obj, memoryview) else obj
+ for obj in x._objects.values()])
expected = x[:]
del a; gc.collect(); gc.collect(); gc.collect()
self.assertEqual(x[:], expected)
- self.assertRaises(TypeError,
- (c_char * 16).from_buffer, "a" * 16)
+ with self.assertRaises(TypeError):
+ (c_char * 16).from_buffer(b"a" * 16)
+ with self.assertRaises(TypeError):
+ (c_char * 16).from_buffer("a" * 16)
- def test_fom_buffer_with_offset(self):
+ def test_from_buffer_with_offset(self):
a = array.array("i", range(16))
x = (c_int * 15).from_buffer(a, sizeof(c_int))
self.assertEqual(x[:], a.tolist()[1:])
- self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int)))
- self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int)))
+ with self.assertRaises(ValueError):
+ c_int.from_buffer(a, -1)
+ with self.assertRaises(ValueError):
+ (c_int * 16).from_buffer(a, sizeof(c_int))
+ with self.assertRaises(ValueError):
+ (c_int * 1).from_buffer(a, 16 * sizeof(c_int))
def test_from_buffer_copy(self):
a = array.array("i", range(16))
@@ -56,26 +68,30 @@ class Test(unittest.TestCase):
a[0], a[-1] = 200, -200
self.assertEqual(x[:], list(range(16)))
- self.assertEqual(x._objects, None)
+ a.append(100)
+ self.assertEqual(x[:], list(range(16)))
- self.assertRaises(ValueError,
- c_int.from_buffer, a, -1)
+ self.assertEqual(x._objects, None)
del a; gc.collect(); gc.collect(); gc.collect()
self.assertEqual(x[:], list(range(16)))
x = (c_char * 16).from_buffer_copy(b"a" * 16)
self.assertEqual(x[:], b"a" * 16)
+ with self.assertRaises(TypeError):
+ (c_char * 16).from_buffer_copy("a" * 16)
- def test_fom_buffer_copy_with_offset(self):
+ def test_from_buffer_copy_with_offset(self):
a = array.array("i", range(16))
x = (c_int * 15).from_buffer_copy(a, sizeof(c_int))
self.assertEqual(x[:], a.tolist()[1:])
- self.assertRaises(ValueError,
- (c_int * 16).from_buffer_copy, a, sizeof(c_int))
- self.assertRaises(ValueError,
- (c_int * 1).from_buffer_copy, a, 16 * sizeof(c_int))
+ with self.assertRaises(ValueError):
+ c_int.from_buffer_copy(a, -1)
+ with self.assertRaises(ValueError):
+ (c_int * 16).from_buffer_copy(a, sizeof(c_int))
+ with self.assertRaises(ValueError):
+ (c_int * 1).from_buffer_copy(a, 16 * sizeof(c_int))
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
index 86e902bafe..976368ef79 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -11,6 +11,9 @@ Release date: TBA
Core and Builtins
-----------------
+- Issue #22896: Avoid using PyObject_AsCharBuffer(), PyObject_AsReadBuffer()
+ and PyObject_AsWriteBuffer().
+
- Issue #21295: Revert some changes (issue #16795) to AST line numbers and
column offsets that constituted a regression.
diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c
index 2bd751a815..52f34793c4 100644
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -284,8 +284,6 @@ unicode_internal_decode(PyObject *self,
{
PyObject *obj;
const char *errors = NULL;
- const char *data;
- Py_ssize_t size;
if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode",
&obj, &errors))
@@ -298,11 +296,16 @@ unicode_internal_decode(PyObject *self,
return codec_tuple(obj, PyUnicode_GET_LENGTH(obj));
}
else {
- if (PyObject_AsReadBuffer(obj, (const void **)&data, &size))
+ Py_buffer view;
+ PyObject *result;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
return NULL;
- return codec_tuple(_PyUnicode_DecodeUnicodeInternal(data, size, errors),
- size);
+ result = codec_tuple(
+ _PyUnicode_DecodeUnicodeInternal(view.buf, view.len, errors),
+ view.len);
+ PyBuffer_Release(&view);
+ return result;
}
}
@@ -727,8 +730,6 @@ unicode_internal_encode(PyObject *self,
{
PyObject *obj;
const char *errors = NULL;
- const char *data;
- Py_ssize_t len, size;
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"unicode_internal codec has been deprecated",
@@ -741,6 +742,7 @@ unicode_internal_encode(PyObject *self,
if (PyUnicode_Check(obj)) {
Py_UNICODE *u;
+ Py_ssize_t len, size;
if (PyUnicode_READY(obj) < 0)
return NULL;
@@ -755,9 +757,13 @@ unicode_internal_encode(PyObject *self,
PyUnicode_GET_LENGTH(obj));
}
else {
- if (PyObject_AsReadBuffer(obj, (const void **)&data, &size))
+ Py_buffer view;
+ PyObject *result;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
return NULL;
- return codec_tuple(PyBytes_FromStringAndSize(data, size), size);
+ result = codec_tuple(PyBytes_FromStringAndSize(view.buf, view.len), view.len);
+ PyBuffer_Release(&view);
+ return result;
}
}
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index f771473aa8..c2889d2ec3 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -463,39 +463,45 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
static PyObject *
CDataType_from_buffer(PyObject *type, PyObject *args)
{
- void *buffer;
- Py_ssize_t buffer_len;
+ Py_buffer buffer;
Py_ssize_t offset = 0;
- PyObject *obj, *result;
+ PyObject *result, *mv;
StgDictObject *dict = PyType_stgdict(type);
assert (dict);
- if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset))
- return NULL;
-
- if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len))
+ if (!PyArg_ParseTuple(args, "w*|n:from_buffer", &buffer, &offset))
return NULL;
if (offset < 0) {
PyErr_SetString(PyExc_ValueError,
"offset cannot be negative");
+ PyBuffer_Release(&buffer);
return NULL;
}
- if (dict->size > buffer_len - offset) {
+ if (dict->size > buffer.len - offset) {
PyErr_Format(PyExc_ValueError,
"Buffer size too small (%zd instead of at least %zd bytes)",
- buffer_len, dict->size + offset);
+ buffer.len, dict->size + offset);
+ PyBuffer_Release(&buffer);
return NULL;
}
- result = PyCData_AtAddress(type, (char *)buffer + offset);
- if (result == NULL)
+ result = PyCData_AtAddress(type, (char *)buffer.buf + offset);
+ if (result == NULL) {
+ PyBuffer_Release(&buffer);
return NULL;
+ }
- Py_INCREF(obj);
- if (-1 == KeepRef((CDataObject *)result, -1, obj)) {
+ mv = PyMemoryView_FromBuffer(&buffer);
+ if (mv == NULL) {
+ PyBuffer_Release(&buffer);
return NULL;
}
+ /* Hack the memoryview so that it will release the buffer. */
+ ((PyMemoryViewObject *)mv)->mbuf->master.obj = buffer.obj;
+ ((PyMemoryViewObject *)mv)->view.obj = buffer.obj;
+ if (-1 == KeepRef((CDataObject *)result, -1, mv))
+ result = NULL;
return result;
}
@@ -508,37 +514,36 @@ GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject *
CDataType_from_buffer_copy(PyObject *type, PyObject *args)
{
- const void *buffer;
- Py_ssize_t buffer_len;
+ Py_buffer buffer;
Py_ssize_t offset = 0;
- PyObject *obj, *result;
+ PyObject *result;
StgDictObject *dict = PyType_stgdict(type);
assert (dict);
- if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset))
- return NULL;
-
- if (-1 == PyObject_AsReadBuffer(obj, (const void**)&buffer, &buffer_len))
+ if (!PyArg_ParseTuple(args, "y*|n:from_buffer", &buffer, &offset))
return NULL;
if (offset < 0) {
PyErr_SetString(PyExc_ValueError,
"offset cannot be negative");
+ PyBuffer_Release(&buffer);
return NULL;
}
- if (dict->size > buffer_len - offset) {
+ if (dict->size > buffer.len - offset) {
PyErr_Format(PyExc_ValueError,
"Buffer size too small (%zd instead of at least %zd bytes)",
- buffer_len, dict->size + offset);
+ buffer.len, dict->size + offset);
+ PyBuffer_Release(&buffer);
return NULL;
}
result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
- if (result == NULL)
- return NULL;
- memcpy(((CDataObject *)result)->b_ptr,
- (char *)buffer+offset, dict->size);
+ if (result != NULL) {
+ memcpy(((CDataObject *)result)->b_ptr,
+ (char *)buffer.buf + offset, dict->size);
+ }
+ PyBuffer_Release(&buffer);
return result;
}
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 54840bb88a..57c207341c 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -437,17 +437,18 @@ PyDoc_STRVAR(readinto_doc,
"is set not to block as has no data to read.");
static PyObject *
-bytesio_readinto(bytesio *self, PyObject *buffer)
+bytesio_readinto(bytesio *self, PyObject *arg)
{
- void *raw_buffer;
+ Py_buffer buffer;
Py_ssize_t len, n;
CHECK_CLOSED(self);
- if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1)
+ if (!PyArg_Parse(arg, "w*", &buffer))
return NULL;
/* adjust invalid sizes */
+ len = buffer.len;
n = self->string_size - self->pos;
if (len > n) {
len = n;
@@ -455,10 +456,11 @@ bytesio_readinto(bytesio *self, PyObject *buffer)
len = 0;
}
- memcpy(raw_buffer, self->buf + self->pos, len);
+ memcpy(buffer.buf, self->buf + self->pos, len);
assert(self->pos + len < PY_SSIZE_T_MAX);
assert(len >= 0);
self->pos += len;
+ PyBuffer_Release(&buffer);
return PyLong_FromSsize_t(len);
}
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 535464dbf1..2e8cab5554 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -522,19 +522,20 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
return -1;
sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
} else if (PyObject_CheckBuffer(py_val)) {
- const char* buffer;
- Py_ssize_t buflen;
- if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
+ Py_buffer view;
+ if (PyObject_GetBuffer(py_val, &view, PyBUF_SIMPLE) != 0) {
PyErr_SetString(PyExc_ValueError,
"could not convert BLOB to buffer");
return -1;
}
- if (buflen > INT_MAX) {
+ if (view.len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"BLOB longer than INT_MAX bytes");
+ PyBuffer_Release(&view);
return -1;
}
- sqlite3_result_blob(context, buffer, (int)buflen, SQLITE_TRANSIENT);
+ sqlite3_result_blob(context, view.buf, (int)view.len, SQLITE_TRANSIENT);
+ PyBuffer_Release(&view);
} else {
return -1;
}
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c
index 34babfd750..e87063341d 100644
--- a/Modules/_sqlite/statement.c
+++ b/Modules/_sqlite/statement.c
@@ -94,7 +94,6 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter)
{
int rc = SQLITE_OK;
- const char* buffer;
char* string;
Py_ssize_t buflen;
parameter_type paramtype;
@@ -145,18 +144,22 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec
}
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
break;
- case TYPE_BUFFER:
- if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) {
+ case TYPE_BUFFER: {
+ Py_buffer view;
+ if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
return -1;
}
- if (buflen > INT_MAX) {
+ if (view.len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"BLOB longer than INT_MAX bytes");
+ PyBuffer_Release(&view);
return -1;
}
- rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
+ rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
+ PyBuffer_Release(&view);
break;
+ }
case TYPE_UNKNOWN:
rc = -1;
}
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 1de94e406e..ad9959e1e5 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1842,8 +1842,8 @@ static PyObject *
s_pack_into(PyObject *self, PyObject *args)
{
PyStructObject *soself;
- char *buffer;
- Py_ssize_t buffer_len, offset;
+ Py_buffer buffer;
+ Py_ssize_t offset;
/* Validate arguments. +1 is for the first arg as buffer. */
soself = (PyStructObject *)self;
@@ -1868,34 +1868,37 @@ s_pack_into(PyObject *self, PyObject *args)
}
/* Extract a writable memory buffer from the first argument */
- if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
- (void**)&buffer, &buffer_len) == -1 ) {
+ if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buffer))
return NULL;
- }
- assert( buffer_len >= 0 );
+ assert(buffer.len >= 0);
/* Extract the offset from the first argument */
offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError);
- if (offset == -1 && PyErr_Occurred())
+ if (offset == -1 && PyErr_Occurred()) {
+ PyBuffer_Release(&buffer);
return NULL;
+ }
/* Support negative offsets. */
if (offset < 0)
- offset += buffer_len;
+ offset += buffer.len;
/* Check boundaries */
- if (offset < 0 || (buffer_len - offset) < soself->s_size) {
+ if (offset < 0 || (buffer.len - offset) < soself->s_size) {
PyErr_Format(StructError,
"pack_into requires a buffer of at least %zd bytes",
soself->s_size);
+ PyBuffer_Release(&buffer);
return NULL;
}
/* Call the guts */
- if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
+ if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset) != 0) {
+ PyBuffer_Release(&buffer);
return NULL;
}
+ PyBuffer_Release(&buffer);
Py_RETURN_NONE;
}
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 9ed3f922cc..7e3121a932 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -250,28 +250,7 @@ PyObject_AsCharBuffer(PyObject *obj,
const char **buffer,
Py_ssize_t *buffer_len)
{
- PyBufferProcs *pb;
- Py_buffer view;
-
- if (obj == NULL || buffer == NULL || buffer_len == NULL) {
- null_error();
- return -1;
- }
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL || pb->bf_getbuffer == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected bytes, bytearray "
- "or buffer compatible object");
- return -1;
- }
- if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
-
- *buffer = view.buf;
- *buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
- return 0;
+ return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len);
}
int
@@ -295,28 +274,18 @@ int PyObject_AsReadBuffer(PyObject *obj,
const void **buffer,
Py_ssize_t *buffer_len)
{
- PyBufferProcs *pb;
Py_buffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
return -1;
}
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getbuffer == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected an object with a buffer interface");
+ if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
return -1;
- }
-
- if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
*buffer = view.buf;
*buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
+ PyBuffer_Release(&view);
return 0;
}
@@ -342,9 +311,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
*buffer = view.buf;
*buffer_len = view.len;
- if (pb->bf_releasebuffer != NULL)
- (*pb->bf_releasebuffer)(obj, &view);
- Py_XDECREF(view.obj);
+ PyBuffer_Release(&view);
return 0;
}
@@ -353,13 +320,15 @@ int PyObject_AsWriteBuffer(PyObject *obj,
int
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
{
- if (!PyObject_CheckBuffer(obj)) {
+ PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
+
+ if (pb == NULL || pb->bf_getbuffer == NULL) {
PyErr_Format(PyExc_TypeError,
"'%.100s' does not support the buffer interface",
Py_TYPE(obj)->tp_name);
return -1;
}
- return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+ return (*pb->bf_getbuffer)(obj, view, flags);
}
static int
@@ -652,10 +621,14 @@ void
PyBuffer_Release(Py_buffer *view)
{
PyObject *obj = view->obj;
- if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
- Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
- Py_XDECREF(obj);
+ PyBufferProcs *pb;
+ if (obj == NULL)
+ return;
+ pb = Py_TYPE(obj)->tp_as_buffer;
+ if (pb && pb->bf_releasebuffer)
+ pb->bf_releasebuffer(obj, view);
view->obj = NULL;
+ Py_DECREF(obj);
}
PyObject *
@@ -1249,8 +1222,7 @@ PyNumber_Long(PyObject *o)
{
PyNumberMethods *m;
PyObject *trunc_func;
- const char *buffer;
- Py_ssize_t buffer_len;
+ Py_buffer view;
_Py_IDENTIFIER(__trunc__);
if (o == NULL)
@@ -1288,21 +1260,22 @@ PyNumber_Long(PyObject *o)
if (PyErr_Occurred())
return NULL;
- if (PyBytes_Check(o))
+ if (PyUnicode_Check(o))
+ /* The below check is done in PyLong_FromUnicode(). */
+ return PyLong_FromUnicodeObject(o, 10);
+
+ if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) {
/* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular int('9\x005') must raise an
* exception, not truncate at the null.
*/
- return _PyLong_FromBytes(PyBytes_AS_STRING(o),
- PyBytes_GET_SIZE(o), 10);
- if (PyUnicode_Check(o))
- /* The above check is done in PyLong_FromUnicode(). */
- return PyLong_FromUnicodeObject(o, 10);
- if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
- return _PyLong_FromBytes(buffer, buffer_len, 10);
+ PyObject *result = _PyLong_FromBytes(view.buf, view.len, 10);
+ PyBuffer_Release(&view);
+ return result;
+ }
- return type_error("int() argument must be a string or a "
- "number, not '%.200s'", o);
+ return type_error("int() argument must be a string, a bytes-like object "
+ "or a number, not '%.200s'", o);
}
PyObject *
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index d72abb7bb2..f5eb321928 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -74,24 +74,6 @@ bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
obj->ob_exports--;
}
-static Py_ssize_t
-_getbuffer(PyObject *obj, Py_buffer *view)
-{
- PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
-
- if (buffer == NULL || buffer->bf_getbuffer == NULL)
- {
- PyErr_Format(PyExc_TypeError,
- "Type %.100s doesn't support the buffer API",
- Py_TYPE(obj)->tp_name);
- return -1;
- }
-
- if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
- return -1;
- return view->len;
-}
-
static int
_canresize(PyByteArrayObject *self)
{
@@ -262,8 +244,8 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
va.len = -1;
vb.len = -1;
- if (_getbuffer(a, &va) < 0 ||
- _getbuffer(b, &vb) < 0) {
+ if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
+ PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
goto done;
@@ -304,7 +286,7 @@ bytearray_iconcat(PyByteArrayObject *self, PyObject *other)
Py_ssize_t size;
Py_buffer vo;
- if (_getbuffer(other, &vo) < 0) {
+ if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);
return NULL;
@@ -562,14 +544,14 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
needed = 0;
}
else {
- if (_getbuffer(values, &vbytes) < 0) {
- PyErr_Format(PyExc_TypeError,
- "can't set bytearray slice from %.100s",
- Py_TYPE(values)->tp_name);
- return -1;
- }
- needed = vbytes.len;
- bytes = vbytes.buf;
+ if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) {
+ PyErr_Format(PyExc_TypeError,
+ "can't set bytearray slice from %.100s",
+ Py_TYPE(values)->tp_name);
+ return -1;
+ }
+ needed = vbytes.len;
+ bytes = vbytes.buf;
}
if (lo < 0)
@@ -1012,18 +994,18 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
Py_RETURN_NOTIMPLEMENTED;
}
- self_size = _getbuffer(self, &self_bytes);
- if (self_size < 0) {
+ if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED;
}
+ self_size = self_bytes.len;
- other_size = _getbuffer(other, &other_bytes);
- if (other_size < 0) {
+ if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
PyErr_Clear();
PyBuffer_Release(&self_bytes);
Py_RETURN_NOTIMPLEMENTED;
}
+ other_size = other_bytes.len;
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the objects differ */
@@ -1135,7 +1117,7 @@ bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
return -2;
if (subobj) {
- if (_getbuffer(subobj, &subbuf) < 0)
+ if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
return -2;
sub = subbuf.buf;
@@ -1203,7 +1185,7 @@ bytearray_count(PyByteArrayObject *self, PyObject *args)
return NULL;
if (sub_obj) {
- if (_getbuffer(sub_obj, &vsub) < 0)
+ if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
@@ -1318,7 +1300,7 @@ bytearray_contains(PyObject *self, PyObject *arg)
Py_buffer varg;
Py_ssize_t pos;
PyErr_Clear();
- if (_getbuffer(arg, &varg) < 0)
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return -1;
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0);
@@ -1349,7 +1331,7 @@ _bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start
str = PyByteArray_AS_STRING(self);
- if (_getbuffer(substr, &vsubstr) < 0)
+ if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0)
return -1;
ADJUST_INDICES(start, end, len);
@@ -1493,7 +1475,7 @@ bytearray_translate(PyByteArrayObject *self, PyObject *args)
if (tableobj == Py_None) {
table = NULL;
tableobj = NULL;
- } else if (_getbuffer(tableobj, &vtable) < 0) {
+ } else if (PyObject_GetBuffer(tableobj, &vtable, PyBUF_SIMPLE) != 0) {
return NULL;
} else {
if (vtable.len != 256) {
@@ -1506,7 +1488,7 @@ bytearray_translate(PyByteArrayObject *self, PyObject *args)
}
if (delobj != NULL) {
- if (_getbuffer(delobj, &vdel) < 0) {
+ if (PyObject_GetBuffer(delobj, &vdel, PyBUF_SIMPLE) != 0) {
if (tableobj != NULL)
PyBuffer_Release(&vtable);
return NULL;
@@ -2070,26 +2052,20 @@ given, only the first count occurrences are replaced.");
static PyObject *
bytearray_replace(PyByteArrayObject *self, PyObject *args)
{
+ PyObject *res;
+ Py_buffer old = {NULL, NULL};
+ Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1;
- PyObject *from, *to, *res;
- Py_buffer vfrom, vto;
- if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
+ if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count))
return NULL;
- if (_getbuffer(from, &vfrom) < 0)
- return NULL;
- if (_getbuffer(to, &vto) < 0) {
- PyBuffer_Release(&vfrom);
- return NULL;
- }
-
res = (PyObject *)replace((PyByteArrayObject *) self,
- vfrom.buf, vfrom.len,
- vto.buf, vto.len, count);
+ (const char *)old.buf, old.len,
+ (const char *)new.buf, new.len, count);
- PyBuffer_Release(&vfrom);
- PyBuffer_Release(&vto);
+ PyBuffer_Release(&old);
+ PyBuffer_Release(&new);
return res;
}
@@ -2120,7 +2096,7 @@ bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
if (subobj == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
- if (_getbuffer(subobj, &vsub) < 0)
+ if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@@ -2215,7 +2191,7 @@ bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
if (subobj == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
- if (_getbuffer(subobj, &vsub) < 0)
+ if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@@ -2503,7 +2479,7 @@ bytearray_strip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
- if (_getbuffer(arg, &varg) < 0)
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;
@@ -2540,7 +2516,7 @@ bytearray_lstrip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
- if (_getbuffer(arg, &varg) < 0)
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;
@@ -2574,7 +2550,7 @@ bytearray_rstrip(PyByteArrayObject *self, PyObject *args)
argsize = 6;
}
else {
- if (_getbuffer(arg, &varg) < 0)
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return NULL;
argptr = (char *) varg.buf;
argsize = varg.len;
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index 4e8107b491..9ff7ace0dd 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -363,41 +363,20 @@ for use in the bytes or bytearray translate method where each byte\n\
in frm is mapped to the byte at the same position in to.\n\
The bytes objects frm and to must be of the same length.");
-static Py_ssize_t
-_getbuffer(PyObject *obj, Py_buffer *view)
-{
- PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
-
- if (buffer == NULL || buffer->bf_getbuffer == NULL)
- {
- PyErr_Format(PyExc_TypeError,
- "Type %.100s doesn't support the buffer API",
- Py_TYPE(obj)->tp_name);
- return -1;
- }
-
- if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
- return -1;
- return view->len;
-}
-
PyObject *
_Py_bytes_maketrans(PyObject *args)
{
- PyObject *frm, *to, *res = NULL;
- Py_buffer bfrm, bto;
+ PyObject *res = NULL;
+ Py_buffer bfrm = {NULL, NULL};
+ Py_buffer bto = {NULL, NULL};
Py_ssize_t i;
char *p;
bfrm.len = -1;
bto.len = -1;
- if (!PyArg_ParseTuple(args, "OO:maketrans", &frm, &to))
- return NULL;
- if (_getbuffer(frm, &bfrm) < 0)
+ if (!PyArg_ParseTuple(args, "y*y*:maketrans", &bfrm, &bto))
return NULL;
- if (_getbuffer(to, &bto) < 0)
- goto done;
if (bfrm.len != bto.len) {
PyErr_Format(PyExc_ValueError,
"maketrans arguments must have same length");
@@ -415,9 +394,9 @@ _Py_bytes_maketrans(PyObject *args)
}
done:
- if (bfrm.len != -1)
+ if (bfrm.obj != NULL)
PyBuffer_Release(&bfrm);
- if (bto.len != -1)
+ if (bfrm.obj != NULL)
PyBuffer_Release(&bto);
return res;
}
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index a3ccbcfd61..e56dbed355 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -7,33 +7,6 @@
#include "bytes_methods.h"
#include <stddef.h>
-static Py_ssize_t
-_getbuffer(PyObject *obj, Py_buffer *view)
-{
- PyBufferProcs *bufferprocs;
- if (PyBytes_CheckExact(obj)) {
- /* Fast path, e.g. for .join() of many bytes objects */
- Py_INCREF(obj);
- view->obj = obj;
- view->buf = PyBytes_AS_STRING(obj);
- view->len = PyBytes_GET_SIZE(obj);
- return view->len;
- }
-
- bufferprocs = Py_TYPE(obj)->tp_as_buffer;
- if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL)
- {
- PyErr_Format(PyExc_TypeError,
- "Type %.100s doesn't support the buffer API",
- Py_TYPE(obj)->tp_name);
- return -1;
- }
-
- if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
- return -1;
- return view->len;
-}
-
#ifdef COUNT_ALLOCS
Py_ssize_t null_strings, one_strings;
#endif
@@ -695,8 +668,8 @@ bytes_concat(PyObject *a, PyObject *b)
va.len = -1;
vb.len = -1;
- if (_getbuffer(a, &va) < 0 ||
- _getbuffer(b, &vb) < 0) {
+ if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
+ PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
goto done;
@@ -794,7 +767,7 @@ bytes_contains(PyObject *self, PyObject *arg)
Py_buffer varg;
Py_ssize_t pos;
PyErr_Clear();
- if (_getbuffer(arg, &varg) < 0)
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return -1;
pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0);
@@ -1048,7 +1021,7 @@ bytes_split(PyBytesObject *self, PyObject *args, PyObject *kwds)
maxsplit = PY_SSIZE_T_MAX;
if (subobj == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
- if (_getbuffer(subobj, &vsub) < 0)
+ if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@@ -1068,21 +1041,19 @@ found, returns B and two empty bytes objects.");
static PyObject *
bytes_partition(PyBytesObject *self, PyObject *sep_obj)
{
- const char *sep;
- Py_ssize_t sep_len;
+ Py_buffer sep = {NULL, NULL};
+ PyObject *res;
- if (PyBytes_Check(sep_obj)) {
- sep = PyBytes_AS_STRING(sep_obj);
- sep_len = PyBytes_GET_SIZE(sep_obj);
- }
- else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
+ if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0)
return NULL;
- return stringlib_partition(
+ res = stringlib_partition(
(PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
- sep_obj, sep, sep_len
+ sep_obj, sep.buf, sep.len
);
+ PyBuffer_Release(&sep);
+ return res;
}
PyDoc_STRVAR(rpartition__doc__,
@@ -1096,21 +1067,19 @@ bytes objects and B.");
static PyObject *
bytes_rpartition(PyBytesObject *self, PyObject *sep_obj)
{
- const char *sep;
- Py_ssize_t sep_len;
+ Py_buffer sep = {NULL, NULL};
+ PyObject *res;
- if (PyBytes_Check(sep_obj)) {
- sep = PyBytes_AS_STRING(sep_obj);
- sep_len = PyBytes_GET_SIZE(sep_obj);
- }
- else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
+ if (PyObject_GetBuffer(sep_obj, &sep, PyBUF_SIMPLE) != 0)
return NULL;
- return stringlib_rpartition(
+ res = stringlib_rpartition(
(PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
- sep_obj, sep, sep_len
+ sep_obj, sep.buf, sep.len
);
+ PyBuffer_Release(&sep);
+ return res;
}
PyDoc_STRVAR(rsplit__doc__,
@@ -1140,7 +1109,7 @@ bytes_rsplit(PyBytesObject *self, PyObject *args, PyObject *kwds)
maxsplit = PY_SSIZE_T_MAX;
if (subobj == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
- if (_getbuffer(subobj, &vsub) < 0)
+ if (PyObject_GetBuffer(subobj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
@@ -1202,7 +1171,7 @@ bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
return -2;
if (subobj) {
- if (_getbuffer(subobj, &subbuf) < 0)
+ if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
return -2;
sub = subbuf.buf;
@@ -1317,7 +1286,7 @@ do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj)
Py_ssize_t seplen;
Py_ssize_t i, j;
- if (_getbuffer(sepobj, &vsep) < 0)
+ if (PyObject_GetBuffer(sepobj, &vsep, PyBUF_SIMPLE) != 0)
return NULL;
sep = vsep.buf;
seplen = vsep.len;
@@ -1462,7 +1431,7 @@ bytes_count(PyBytesObject *self, PyObject *args)
return NULL;
if (sub_obj) {
- if (_getbuffer(sub_obj, &vsub) < 0)
+ if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
@@ -1498,6 +1467,8 @@ static PyObject *
bytes_translate(PyBytesObject *self, PyObject *args)
{
char *input, *output;
+ Py_buffer table_view = {NULL, NULL};
+ Py_buffer del_table_view = {NULL, NULL};
const char *table;
Py_ssize_t i, c, changed = 0;
PyObject *input_obj = (PyObject*)self;
@@ -1519,12 +1490,17 @@ bytes_translate(PyBytesObject *self, PyObject *args)
table = NULL;
tablen = 256;
}
- else if (PyObject_AsCharBuffer(tableobj, &table, &tablen))
- return NULL;
+ else {
+ if (PyObject_GetBuffer(tableobj, &table_view, PyBUF_SIMPLE) != 0)
+ return NULL;
+ table = table_view.buf;
+ tablen = table_view.len;
+ }
if (tablen != 256) {
PyErr_SetString(PyExc_ValueError,
"translation table must be 256 characters long");
+ PyBuffer_Release(&table_view);
return NULL;
}
@@ -1533,8 +1509,14 @@ bytes_translate(PyBytesObject *self, PyObject *args)
del_table = PyBytes_AS_STRING(delobj);
dellen = PyBytes_GET_SIZE(delobj);
}
- else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen))
- return NULL;
+ else {
+ if (PyObject_GetBuffer(delobj, &del_table_view, PyBUF_SIMPLE) != 0) {
+ PyBuffer_Release(&table_view);
+ return NULL;
+ }
+ del_table = del_table_view.buf;
+ dellen = del_table_view.len;
+ }
}
else {
del_table = NULL;
@@ -1543,8 +1525,11 @@ bytes_translate(PyBytesObject *self, PyObject *args)
inlen = PyBytes_GET_SIZE(input_obj);
result = PyBytes_FromStringAndSize((char *)NULL, inlen);
- if (result == NULL)
+ if (result == NULL) {
+ PyBuffer_Release(&del_table_view);
+ PyBuffer_Release(&table_view);
return NULL;
+ }
output_start = output = PyBytes_AsString(result);
input = PyBytes_AS_STRING(input_obj);
@@ -1555,11 +1540,14 @@ bytes_translate(PyBytesObject *self, PyObject *args)
if (Py_CHARMASK((*output++ = table[c])) != c)
changed = 1;
}
- if (changed || !PyBytes_CheckExact(input_obj))
- return result;
- Py_DECREF(result);
- Py_INCREF(input_obj);
- return input_obj;
+ if (!changed && PyBytes_CheckExact(input_obj)) {
+ Py_INCREF(input_obj);
+ Py_DECREF(result);
+ result = input_obj;
+ }
+ PyBuffer_Release(&del_table_view);
+ PyBuffer_Release(&table_view);
+ return result;
}
if (table == NULL) {
@@ -1569,9 +1557,11 @@ bytes_translate(PyBytesObject *self, PyObject *args)
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table[i]);
}
+ PyBuffer_Release(&table_view);
for (i = 0; i < dellen; i++)
trans_table[(int) Py_CHARMASK(del_table[i])] = -1;
+ PyBuffer_Release(&del_table_view);
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
@@ -2100,31 +2090,21 @@ given, only first count occurances are replaced.");
static PyObject *
bytes_replace(PyBytesObject *self, PyObject *args)
{
+ PyObject *res;
+ Py_buffer old = {NULL, NULL};
+ Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1;
- PyObject *from, *to;
- const char *from_s, *to_s;
- Py_ssize_t from_len, to_len;
-
- if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
- return NULL;
- if (PyBytes_Check(from)) {
- from_s = PyBytes_AS_STRING(from);
- from_len = PyBytes_GET_SIZE(from);
- }
- else if (PyObject_AsCharBuffer(from, &from_s, &from_len))
+ if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count))
return NULL;
- if (PyBytes_Check(to)) {
- to_s = PyBytes_AS_STRING(to);
- to_len = PyBytes_GET_SIZE(to);
- }
- else if (PyObject_AsCharBuffer(to, &to_s, &to_len))
- return NULL;
+ res = (PyObject *)replace((PyBytesObject *) self,
+ (const char *)old.buf, old.len,
+ (const char *)new.buf, new.len, count);
- return (PyObject *)replace((PyBytesObject *) self,
- from_s, from_len,
- to_s, to_len, count);
+ PyBuffer_Release(&old);
+ PyBuffer_Release(&new);
+ return res;
}
/** End DALKE **/
@@ -2139,6 +2119,7 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
{
Py_ssize_t len = PyBytes_GET_SIZE(self);
Py_ssize_t slen;
+ Py_buffer sub_view = {NULL, NULL};
const char* sub;
const char* str;
@@ -2146,8 +2127,12 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
sub = PyBytes_AS_STRING(substr);
slen = PyBytes_GET_SIZE(substr);
}
- else if (PyObject_AsCharBuffer(substr, &sub, &slen))
- return -1;
+ else {
+ if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
+ return -1;
+ sub = sub_view.buf;
+ slen = sub_view.len;
+ }
str = PyBytes_AS_STRING(self);
ADJUST_INDICES(start, end, len);
@@ -2155,17 +2140,25 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
if (direction < 0) {
/* startswith */
if (start+slen > len)
- return 0;
+ goto notfound;
} else {
/* endswith */
if (end-start < slen || start > len)
- return 0;
+ goto notfound;
if (end-slen > start)
start = end - slen;
}
- if (end-start >= slen)
- return ! memcmp(str+start, sub, slen);
+ if (end-start < slen)
+ goto notfound;
+ if (memcmp(str+start, sub, slen) != 0)
+ goto notfound;
+
+ PyBuffer_Release(&sub_view);
+ return 1;
+
+notfound:
+ PyBuffer_Release(&sub_view);
return 0;
}
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 0128120e7f..7f4cdd9b35 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -767,6 +767,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
int got_bracket=0;
PyObject *s_buffer = NULL;
Py_ssize_t len;
+ Py_buffer view = {NULL, NULL};
if (PyUnicode_Check(v)) {
s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
@@ -776,7 +777,11 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (s == NULL)
goto error;
}
- else if (PyObject_AsCharBuffer(v, &s, &len)) {
+ else if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) == 0) {
+ s = (const char *)view.buf;
+ len = view.len;
+ }
+ else {
PyErr_Format(PyExc_TypeError,
"complex() argument must be a string or a number, not '%.200s'",
Py_TYPE(v)->tp_name);
@@ -890,6 +895,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (s-start != len)
goto parse_error;
+ PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return complex_subtype_from_doubles(type, x, y);
@@ -897,6 +903,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string");
error:
+ PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return NULL;
}
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 873fbc61bd..c76eca80c6 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1922,8 +1922,6 @@ static int
UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
{
PyUnicodeErrorObject *ude;
- const char *data;
- Py_ssize_t size;
if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
return -1;
@@ -1944,21 +1942,27 @@ UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1;
}
- if (!PyBytes_Check(ude->object)) {
- if (PyObject_AsReadBuffer(ude->object, (const void **)&data, &size)) {
- ude->encoding = ude->object = ude->reason = NULL;
- return -1;
- }
- ude->object = PyBytes_FromStringAndSize(data, size);
- }
- else {
- Py_INCREF(ude->object);
- }
-
Py_INCREF(ude->encoding);
+ Py_INCREF(ude->object);
Py_INCREF(ude->reason);
+ if (!PyBytes_Check(ude->object)) {
+ Py_buffer view;
+ if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0)
+ goto error;
+ Py_CLEAR(ude->object);
+ ude->object = PyBytes_FromStringAndSize(view.buf, view.len);
+ PyBuffer_Release(&view);
+ if (!ude->object)
+ goto error;
+ }
return 0;
+
+error:
+ Py_CLEAR(ude->encoding);
+ Py_CLEAR(ude->object);
+ Py_CLEAR(ude->reason);
+ return -1;
}
static PyObject *
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 05b7679553..33e30cafda 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -131,6 +131,7 @@ PyFloat_FromString(PyObject *v)
double x;
PyObject *s_buffer = NULL;
Py_ssize_t len;
+ Py_buffer view = {NULL, NULL};
PyObject *result = NULL;
if (PyUnicode_Check(v)) {
@@ -143,7 +144,11 @@ PyFloat_FromString(PyObject *v)
return NULL;
}
}
- else if (PyObject_AsCharBuffer(v, &s, &len)) {
+ else if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) == 0) {
+ s = (const char *)view.buf;
+ len = view.len;
+ }
+ else {
PyErr_Format(PyExc_TypeError,
"float() argument must be a string or a number, not '%.200s'",
Py_TYPE(v)->tp_name);
@@ -170,6 +175,7 @@ PyFloat_FromString(PyObject *v)
else
result = PyFloat_FromDouble(x);
+ PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return result;
}
diff --git a/Objects/stringlib/join.h b/Objects/stringlib/join.h
index 35eb984352..cbf81be170 100644
--- a/Objects/stringlib/join.h
+++ b/Objects/stringlib/join.h
@@ -58,7 +58,14 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable)
for (i = 0, nbufs = 0; i < seqlen; i++) {
Py_ssize_t itemlen;
item = PySequence_Fast_GET_ITEM(seq, i);
- if (_getbuffer(item, &buffers[i]) < 0) {
+ if (PyBytes_CheckExact(item)) {
+ /* Fast path. */
+ Py_INCREF(item);
+ buffers[i].obj = item;
+ buffers[i].buf = PyBytes_AS_STRING(item);
+ buffers[i].len = PyBytes_GET_SIZE(item);
+ }
+ else if (PyObject_GetBuffer(item, &buffers[i], PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError,
"sequence item %zd: expected a bytes-like object, "
"%.80s found",
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index d905ba2d94..4b4f979169 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -559,10 +559,10 @@ PyDoc_STRVAR(chr_doc,
Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.");
-static char *
-source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
+static const char *
+source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, Py_buffer *view)
{
- char *str;
+ const char *str;
Py_ssize_t size;
if (PyUnicode_Check(cmd)) {
@@ -571,19 +571,21 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
if (str == NULL)
return NULL;
}
- else if (!PyObject_CheckReadBuffer(cmd)) {
+ else if (PyObject_GetBuffer(cmd, view, PyBUF_SIMPLE) == 0) {
+ str = (const char *)view->buf;
+ size = view->len;
+ }
+ else {
PyErr_Format(PyExc_TypeError,
"%s() arg 1 must be a %s object",
funcname, what);
return NULL;
}
- else if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) {
- return NULL;
- }
if (strlen(str) != size) {
PyErr_SetString(PyExc_TypeError,
"source code string cannot contain null bytes");
+ PyBuffer_Release(view);
return NULL;
}
return str;
@@ -592,7 +594,8 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
static PyObject *
builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
{
- char *str;
+ Py_buffer view = {NULL, NULL};
+ const char *str;
PyObject *filename;
char *startstr;
int mode = -1;
@@ -678,11 +681,12 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
goto finally;
}
- str = source_as_string(cmd, "compile", "string, bytes or AST", &cf);
+ str = source_as_string(cmd, "compile", "string, bytes or AST", &cf, &view);
if (str == NULL)
goto error;
result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize);
+ PyBuffer_Release(&view);
goto finally;
error:
@@ -752,7 +756,8 @@ builtin_eval(PyObject *self, PyObject *args)
{
PyObject *cmd, *result, *tmp = NULL;
PyObject *globals = Py_None, *locals = Py_None;
- char *str;
+ Py_buffer view = {NULL, NULL};
+ const char *str;
PyCompilerFlags cf;
if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals))
@@ -801,7 +806,7 @@ builtin_eval(PyObject *self, PyObject *args)
}
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
- str = source_as_string(cmd, "eval", "string, bytes or code", &cf);
+ str = source_as_string(cmd, "eval", "string, bytes or code", &cf, &view);
if (str == NULL)
return NULL;
@@ -810,6 +815,7 @@ builtin_eval(PyObject *self, PyObject *args)
(void)PyEval_MergeCompilerFlags(&cf);
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
+ PyBuffer_Release(&view);
Py_XDECREF(tmp);
return result;
}
@@ -876,11 +882,12 @@ builtin_exec(PyObject *self, PyObject *args)
v = PyEval_EvalCode(prog, globals, locals);
}
else {
- char *str;
+ Py_buffer view = {NULL, NULL};
+ const char *str;
PyCompilerFlags cf;
cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = source_as_string(prog, "exec",
- "string, bytes or code", &cf);
+ "string, bytes or code", &cf, &view);
if (str == NULL)
return NULL;
if (PyEval_MergeCompilerFlags(&cf))
@@ -888,6 +895,7 @@ builtin_exec(PyObject *self, PyObject *args)
locals, &cf);
else
v = PyRun_String(str, Py_file_input, globals, locals);
+ PyBuffer_Release(&view);
}
if (v == NULL)
return NULL;