Issue #22896: Avoid to use PyObject_AsCharBuffer(), PyObject_AsReadBuffer()

and PyObject_AsWriteBuffer().
This commit is contained in:
Serhiy Storchaka 2015-02-03 01:25:42 +02:00
commit 3dd3e26680
18 changed files with 422 additions and 397 deletions

View File

@ -22,7 +22,7 @@ extern void _Py_bytes_capitalize(char *result, char *s, Py_ssize_t len);
extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len); extern void _Py_bytes_swapcase(char *result, char *s, Py_ssize_t len);
/* The maketrans() static method. */ /* The maketrans() static method. */
extern PyObject* _Py_bytes_maketrans(PyObject *frm, PyObject *to); extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to);
/* Shared __doc__ strings. */ /* Shared __doc__ strings. */
extern const char _Py_isspace__doc__[]; extern const char _Py_isspace__doc__[];

View File

@ -10,7 +10,7 @@ class X(Structure):
self._init_called = True self._init_called = True
class Test(unittest.TestCase): class Test(unittest.TestCase):
def test_fom_buffer(self): def test_from_buffer(self):
a = array.array("i", range(16)) a = array.array("i", range(16))
x = (c_int * 16).from_buffer(a) x = (c_int * 16).from_buffer(a)
@ -23,25 +23,37 @@ class Test(unittest.TestCase):
a[0], a[-1] = 200, -200 a[0], a[-1] = 200, -200
self.assertEqual(x[:], a.tolist()) 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, del x; del y; gc.collect(); gc.collect(); gc.collect()
c_int.from_buffer, a, -1) 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[:] expected = x[:]
del a; gc.collect(); gc.collect(); gc.collect() del a; gc.collect(); gc.collect(); gc.collect()
self.assertEqual(x[:], expected) self.assertEqual(x[:], expected)
self.assertRaises(TypeError, with self.assertRaises(TypeError):
(c_char * 16).from_buffer, "a" * 16) (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)) a = array.array("i", range(16))
x = (c_int * 15).from_buffer(a, sizeof(c_int)) x = (c_int * 15).from_buffer(a, sizeof(c_int))
self.assertEqual(x[:], a.tolist()[1:]) self.assertEqual(x[:], a.tolist()[1:])
self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int))) with self.assertRaises(ValueError):
self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int))) 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): def test_from_buffer_copy(self):
a = array.array("i", range(16)) a = array.array("i", range(16))
@ -56,26 +68,30 @@ class Test(unittest.TestCase):
a[0], a[-1] = 200, -200 a[0], a[-1] = 200, -200
self.assertEqual(x[:], list(range(16))) self.assertEqual(x[:], list(range(16)))
self.assertEqual(x._objects, None) a.append(100)
self.assertEqual(x[:], list(range(16)))
self.assertRaises(ValueError, self.assertEqual(x._objects, None)
c_int.from_buffer, a, -1)
del a; gc.collect(); gc.collect(); gc.collect() del a; gc.collect(); gc.collect(); gc.collect()
self.assertEqual(x[:], list(range(16))) self.assertEqual(x[:], list(range(16)))
x = (c_char * 16).from_buffer_copy(b"a" * 16) x = (c_char * 16).from_buffer_copy(b"a" * 16)
self.assertEqual(x[:], 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)) a = array.array("i", range(16))
x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) x = (c_int * 15).from_buffer_copy(a, sizeof(c_int))
self.assertEqual(x[:], a.tolist()[1:]) self.assertEqual(x[:], a.tolist()[1:])
self.assertRaises(ValueError, with self.assertRaises(ValueError):
(c_int * 16).from_buffer_copy, a, sizeof(c_int)) c_int.from_buffer_copy(a, -1)
self.assertRaises(ValueError, with self.assertRaises(ValueError):
(c_int * 1).from_buffer_copy, a, 16 * sizeof(c_int)) (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__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -10,6 +10,9 @@ Release date: TBA
Core and Builtins 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 - Issue #21295: Revert some changes (issue #16795) to AST line numbers and
column offsets that constituted a regression. column offsets that constituted a regression.

View File

@ -288,8 +288,6 @@ unicode_internal_decode(PyObject *self,
{ {
PyObject *obj; PyObject *obj;
const char *errors = NULL; const char *errors = NULL;
const char *data;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode",
&obj, &errors)) &obj, &errors))
@ -302,11 +300,16 @@ unicode_internal_decode(PyObject *self,
return codec_tuple(obj, PyUnicode_GET_LENGTH(obj)); return codec_tuple(obj, PyUnicode_GET_LENGTH(obj));
} }
else { 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 NULL;
return codec_tuple(_PyUnicode_DecodeUnicodeInternal(data, size, errors), result = codec_tuple(
size); _PyUnicode_DecodeUnicodeInternal(view.buf, view.len, errors),
view.len);
PyBuffer_Release(&view);
return result;
} }
} }
@ -731,8 +734,6 @@ unicode_internal_encode(PyObject *self,
{ {
PyObject *obj; PyObject *obj;
const char *errors = NULL; const char *errors = NULL;
const char *data;
Py_ssize_t len, size;
if (PyErr_WarnEx(PyExc_DeprecationWarning, if (PyErr_WarnEx(PyExc_DeprecationWarning,
"unicode_internal codec has been deprecated", "unicode_internal codec has been deprecated",
@ -745,6 +746,7 @@ unicode_internal_encode(PyObject *self,
if (PyUnicode_Check(obj)) { if (PyUnicode_Check(obj)) {
Py_UNICODE *u; Py_UNICODE *u;
Py_ssize_t len, size;
if (PyUnicode_READY(obj) < 0) if (PyUnicode_READY(obj) < 0)
return NULL; return NULL;
@ -759,9 +761,13 @@ unicode_internal_encode(PyObject *self,
PyUnicode_GET_LENGTH(obj)); PyUnicode_GET_LENGTH(obj));
} }
else { 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 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;
} }
} }

View File

@ -463,39 +463,45 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
static PyObject * static PyObject *
CDataType_from_buffer(PyObject *type, PyObject *args) CDataType_from_buffer(PyObject *type, PyObject *args)
{ {
void *buffer; Py_buffer buffer;
Py_ssize_t buffer_len;
Py_ssize_t offset = 0; Py_ssize_t offset = 0;
PyObject *obj, *result; PyObject *result, *mv;
StgDictObject *dict = PyType_stgdict(type); StgDictObject *dict = PyType_stgdict(type);
assert (dict); assert (dict);
if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) if (!PyArg_ParseTuple(args, "w*|n:from_buffer", &buffer, &offset))
return NULL;
if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len))
return NULL; return NULL;
if (offset < 0) { if (offset < 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"offset cannot be negative"); "offset cannot be negative");
PyBuffer_Release(&buffer);
return NULL; return NULL;
} }
if (dict->size > buffer_len - offset) { if (dict->size > buffer.len - offset) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"Buffer size too small (%zd instead of at least %zd bytes)", "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; return NULL;
} }
result = PyCData_AtAddress(type, (char *)buffer + offset); result = PyCData_AtAddress(type, (char *)buffer.buf + offset);
if (result == NULL) if (result == NULL) {
return NULL; PyBuffer_Release(&buffer);
Py_INCREF(obj);
if (-1 == KeepRef((CDataObject *)result, -1, obj)) {
return NULL; return NULL;
} }
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; return result;
} }
@ -508,37 +514,36 @@ GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject * static PyObject *
CDataType_from_buffer_copy(PyObject *type, PyObject *args) CDataType_from_buffer_copy(PyObject *type, PyObject *args)
{ {
const void *buffer; Py_buffer buffer;
Py_ssize_t buffer_len;
Py_ssize_t offset = 0; Py_ssize_t offset = 0;
PyObject *obj, *result; PyObject *result;
StgDictObject *dict = PyType_stgdict(type); StgDictObject *dict = PyType_stgdict(type);
assert (dict); assert (dict);
if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) if (!PyArg_ParseTuple(args, "y*|n:from_buffer", &buffer, &offset))
return NULL;
if (-1 == PyObject_AsReadBuffer(obj, (const void**)&buffer, &buffer_len))
return NULL; return NULL;
if (offset < 0) { if (offset < 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"offset cannot be negative"); "offset cannot be negative");
PyBuffer_Release(&buffer);
return NULL; return NULL;
} }
if (dict->size > buffer_len - offset) { if (dict->size > buffer.len - offset) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"Buffer size too small (%zd instead of at least %zd bytes)", "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; return NULL;
} }
result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL); result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
if (result == NULL) if (result != NULL) {
return NULL; memcpy(((CDataObject *)result)->b_ptr,
memcpy(((CDataObject *)result)->b_ptr, (char *)buffer.buf + offset, dict->size);
(char *)buffer+offset, dict->size); }
PyBuffer_Release(&buffer);
return result; return result;
} }

View File

@ -553,17 +553,18 @@ PyDoc_STRVAR(readinto_doc,
"is set not to block as has no data to read."); "is set not to block as has no data to read.");
static PyObject * 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; Py_ssize_t len, n;
CHECK_CLOSED(self, NULL); CHECK_CLOSED(self, NULL);
if (PyObject_AsWriteBuffer(buffer, &raw_buffer, &len) == -1) if (!PyArg_Parse(arg, "w*", &buffer))
return NULL; return NULL;
/* adjust invalid sizes */ /* adjust invalid sizes */
len = buffer.len;
n = self->string_size - self->pos; n = self->string_size - self->pos;
if (len > n) { if (len > n) {
len = n; len = n;
@ -571,10 +572,11 @@ bytesio_readinto(bytesio *self, PyObject *buffer)
len = 0; 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(self->pos + len < PY_SSIZE_T_MAX);
assert(len >= 0); assert(len >= 0);
self->pos += len; self->pos += len;
PyBuffer_Release(&buffer);
return PyLong_FromSsize_t(len); return PyLong_FromSsize_t(len);
} }

View File

@ -522,19 +522,20 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val)
return -1; return -1;
sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT); sqlite3_result_text(context, str, -1, SQLITE_TRANSIENT);
} else if (PyObject_CheckBuffer(py_val)) { } else if (PyObject_CheckBuffer(py_val)) {
const char* buffer; Py_buffer view;
Py_ssize_t buflen; if (PyObject_GetBuffer(py_val, &view, PyBUF_SIMPLE) != 0) {
if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"could not convert BLOB to buffer"); "could not convert BLOB to buffer");
return -1; return -1;
} }
if (buflen > INT_MAX) { if (view.len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"BLOB longer than INT_MAX bytes"); "BLOB longer than INT_MAX bytes");
PyBuffer_Release(&view);
return -1; 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 { } else {
return -1; return -1;
} }

View File

@ -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 pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter)
{ {
int rc = SQLITE_OK; int rc = SQLITE_OK;
const char* buffer;
char* string; char* string;
Py_ssize_t buflen; Py_ssize_t buflen;
parameter_type paramtype; 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); rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
break; break;
case TYPE_BUFFER: case TYPE_BUFFER: {
if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) { Py_buffer view;
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
return -1; return -1;
} }
if (buflen > INT_MAX) { if (view.len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"BLOB longer than INT_MAX bytes"); "BLOB longer than INT_MAX bytes");
PyBuffer_Release(&view);
return -1; 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; break;
}
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
rc = -1; rc = -1;
} }

View File

@ -1842,8 +1842,8 @@ static PyObject *
s_pack_into(PyObject *self, PyObject *args) s_pack_into(PyObject *self, PyObject *args)
{ {
PyStructObject *soself; PyStructObject *soself;
char *buffer; Py_buffer buffer;
Py_ssize_t buffer_len, offset; Py_ssize_t offset;
/* Validate arguments. +1 is for the first arg as buffer. */ /* Validate arguments. +1 is for the first arg as buffer. */
soself = (PyStructObject *)self; soself = (PyStructObject *)self;
@ -1868,34 +1868,37 @@ s_pack_into(PyObject *self, PyObject *args)
} }
/* Extract a writable memory buffer from the first argument */ /* Extract a writable memory buffer from the first argument */
if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0), if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buffer))
(void**)&buffer, &buffer_len) == -1 ) {
return NULL; return NULL;
} assert(buffer.len >= 0);
assert( buffer_len >= 0 );
/* Extract the offset from the first argument */ /* Extract the offset from the first argument */
offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError); 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; return NULL;
}
/* Support negative offsets. */ /* Support negative offsets. */
if (offset < 0) if (offset < 0)
offset += buffer_len; offset += buffer.len;
/* Check boundaries */ /* Check boundaries */
if (offset < 0 || (buffer_len - offset) < soself->s_size) { if (offset < 0 || (buffer.len - offset) < soself->s_size) {
PyErr_Format(StructError, PyErr_Format(StructError,
"pack_into requires a buffer of at least %zd bytes", "pack_into requires a buffer of at least %zd bytes",
soself->s_size); soself->s_size);
PyBuffer_Release(&buffer);
return NULL; return NULL;
} }
/* Call the guts */ /* 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; return NULL;
} }
PyBuffer_Release(&buffer);
Py_RETURN_NONE; Py_RETURN_NONE;
} }

View File

@ -250,27 +250,7 @@ PyObject_AsCharBuffer(PyObject *obj,
const char **buffer, const char **buffer,
Py_ssize_t *buffer_len) Py_ssize_t *buffer_len)
{ {
PyBufferProcs *pb; return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len);
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 a bytes-like 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;
} }
int int
@ -294,28 +274,18 @@ int PyObject_AsReadBuffer(PyObject *obj,
const void **buffer, const void **buffer,
Py_ssize_t *buffer_len) Py_ssize_t *buffer_len)
{ {
PyBufferProcs *pb;
Py_buffer view; Py_buffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) { if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error(); null_error();
return -1; return -1;
} }
pb = obj->ob_type->tp_as_buffer; if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
if (pb == NULL ||
pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError,
"expected a bytes-like object");
return -1; return -1;
}
if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
*buffer = view.buf; *buffer = view.buf;
*buffer_len = view.len; *buffer_len = view.len;
if (pb->bf_releasebuffer != NULL) PyBuffer_Release(&view);
(*pb->bf_releasebuffer)(obj, &view);
Py_XDECREF(view.obj);
return 0; return 0;
} }
@ -341,9 +311,7 @@ int PyObject_AsWriteBuffer(PyObject *obj,
*buffer = view.buf; *buffer = view.buf;
*buffer_len = view.len; *buffer_len = view.len;
if (pb->bf_releasebuffer != NULL) PyBuffer_Release(&view);
(*pb->bf_releasebuffer)(obj, &view);
Py_XDECREF(view.obj);
return 0; return 0;
} }
@ -352,13 +320,15 @@ int PyObject_AsWriteBuffer(PyObject *obj,
int int
PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) 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, PyErr_Format(PyExc_TypeError,
"a bytes-like object is required, not '%.100s'", "a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return -1; return -1;
} }
return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); return (*pb->bf_getbuffer)(obj, view, flags);
} }
static int static int
@ -676,10 +646,14 @@ void
PyBuffer_Release(Py_buffer *view) PyBuffer_Release(Py_buffer *view)
{ {
PyObject *obj = view->obj; PyObject *obj = view->obj;
if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer) PyBufferProcs *pb;
Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view); if (obj == NULL)
Py_XDECREF(obj); return;
pb = Py_TYPE(obj)->tp_as_buffer;
if (pb && pb->bf_releasebuffer)
pb->bf_releasebuffer(obj, view);
view->obj = NULL; view->obj = NULL;
Py_DECREF(obj);
} }
PyObject * PyObject *
@ -1288,8 +1262,7 @@ PyNumber_Long(PyObject *o)
{ {
PyNumberMethods *m; PyNumberMethods *m;
PyObject *trunc_func; PyObject *trunc_func;
const char *buffer; Py_buffer view;
Py_ssize_t buffer_len;
_Py_IDENTIFIER(__trunc__); _Py_IDENTIFIER(__trunc__);
if (o == NULL) if (o == NULL)
@ -1327,21 +1300,22 @@ PyNumber_Long(PyObject *o)
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; 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() /* need to do extra error checking that PyLong_FromString()
* doesn't do. In particular int('9\x005') must raise an * doesn't do. In particular int('9\x005') must raise an
* exception, not truncate at the null. * exception, not truncate at the null.
*/ */
return _PyLong_FromBytes(PyBytes_AS_STRING(o), PyObject *result = _PyLong_FromBytes(view.buf, view.len, 10);
PyBytes_GET_SIZE(o), 10); PyBuffer_Release(&view);
if (PyUnicode_Check(o)) return result;
/* 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);
return type_error("int() argument must be a string or a " return type_error("int() argument must be a string, a bytes-like object "
"number, not '%.200s'", o); "or a number, not '%.200s'", o);
} }
PyObject * PyObject *

View File

@ -80,24 +80,6 @@ bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
obj->ob_exports--; 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,
"a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name);
return -1;
}
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
return -1;
return view->len;
}
static int static int
_canresize(PyByteArrayObject *self) _canresize(PyByteArrayObject *self)
{ {
@ -268,8 +250,8 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
va.len = -1; va.len = -1;
vb.len = -1; vb.len = -1;
if (_getbuffer(a, &va) < 0 || if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
_getbuffer(b, &vb) < 0) { PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
goto done; goto done;
@ -335,7 +317,7 @@ bytearray_iconcat(PyByteArrayObject *self, PyObject *other)
Py_ssize_t size; Py_ssize_t size;
Py_buffer vo; 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", PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name); Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);
return NULL; return NULL;
@ -595,14 +577,14 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
needed = 0; needed = 0;
} }
else { else {
if (_getbuffer(values, &vbytes) < 0) { if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"can't set bytearray slice from %.100s", "can't set bytearray slice from %.100s",
Py_TYPE(values)->tp_name); Py_TYPE(values)->tp_name);
return -1; return -1;
} }
needed = vbytes.len; needed = vbytes.len;
bytes = vbytes.buf; bytes = vbytes.buf;
} }
if (lo < 0) if (lo < 0)
@ -1047,18 +1029,18 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
} }
self_size = _getbuffer(self, &self_bytes); if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
if (self_size < 0) {
PyErr_Clear(); PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
} }
self_size = self_bytes.len;
other_size = _getbuffer(other, &other_bytes); if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
if (other_size < 0) {
PyErr_Clear(); PyErr_Clear();
PyBuffer_Release(&self_bytes); PyBuffer_Release(&self_bytes);
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
} }
other_size = other_bytes.len;
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the objects differ */ /* Shortcut: if the lengths differ, the objects differ */
@ -1170,7 +1152,7 @@ bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
return -2; return -2;
if (subobj) { if (subobj) {
if (_getbuffer(subobj, &subbuf) < 0) if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
return -2; return -2;
sub = subbuf.buf; sub = subbuf.buf;
@ -1238,7 +1220,7 @@ bytearray_count(PyByteArrayObject *self, PyObject *args)
return NULL; return NULL;
if (sub_obj) { if (sub_obj) {
if (_getbuffer(sub_obj, &vsub) < 0) if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
@ -1397,7 +1379,7 @@ bytearray_contains(PyObject *self, PyObject *arg)
Py_buffer varg; Py_buffer varg;
Py_ssize_t pos; Py_ssize_t pos;
PyErr_Clear(); PyErr_Clear();
if (_getbuffer(arg, &varg) < 0) if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return -1; return -1;
pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0); varg.buf, varg.len, 0);
@ -1428,7 +1410,7 @@ _bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start
str = PyByteArray_AS_STRING(self); str = PyByteArray_AS_STRING(self);
if (_getbuffer(substr, &vsubstr) < 0) if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0)
return -1; return -1;
ADJUST_INDICES(start, end, len); ADJUST_INDICES(start, end, len);
@ -1621,7 +1603,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_rig
if (table == Py_None) { if (table == Py_None) {
table_chars = NULL; table_chars = NULL;
table = NULL; table = NULL;
} else if (_getbuffer(table, &vtable) < 0) { } else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) {
return NULL; return NULL;
} else { } else {
if (vtable.len != 256) { if (vtable.len != 256) {
@ -1634,7 +1616,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_rig
} }
if (deletechars != NULL) { if (deletechars != NULL) {
if (_getbuffer(deletechars, &vdel) < 0) { if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) {
if (table != NULL) if (table != NULL)
PyBuffer_Release(&vtable); PyBuffer_Release(&vtable);
return NULL; return NULL;
@ -1699,8 +1681,8 @@ done:
@staticmethod @staticmethod
bytearray.maketrans bytearray.maketrans
frm: object frm: Py_buffer
to: object to: Py_buffer
/ /
Return a translation table useable for the bytes or bytearray translate method. Return a translation table useable for the bytes or bytearray translate method.
@ -1726,28 +1708,35 @@ PyDoc_STRVAR(bytearray_maketrans__doc__,
{"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__}, {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__},
static PyObject * static PyObject *
bytearray_maketrans_impl(PyObject *frm, PyObject *to); bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to);
static PyObject * static PyObject *
bytearray_maketrans(void *null, PyObject *args) bytearray_maketrans(void *null, PyObject *args)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *frm; Py_buffer frm = {NULL, NULL};
PyObject *to; Py_buffer to = {NULL, NULL};
if (!PyArg_UnpackTuple(args, "maketrans", if (!PyArg_ParseTuple(args,
2, 2, "y*y*:maketrans",
&frm, &to)) &frm, &to))
goto exit; goto exit;
return_value = bytearray_maketrans_impl(frm, to); return_value = bytearray_maketrans_impl(&frm, &to);
exit: exit:
/* Cleanup for frm */
if (frm.obj)
PyBuffer_Release(&frm);
/* Cleanup for to */
if (to.obj)
PyBuffer_Release(&to);
return return_value; return return_value;
} }
static PyObject * static PyObject *
bytearray_maketrans_impl(PyObject *frm, PyObject *to) bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
/*[clinic end generated code: output=307752019d9b25b5 input=ea9bdc6b328c15e2]*/ /*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/
{ {
return _Py_bytes_maketrans(frm, to); return _Py_bytes_maketrans(frm, to);
} }
@ -2243,8 +2232,8 @@ replace(PyByteArrayObject *self,
/*[clinic input] /*[clinic input]
bytearray.replace bytearray.replace
old: object old: Py_buffer
new: object new: Py_buffer
count: Py_ssize_t = -1 count: Py_ssize_t = -1
Maximum number of occurrences to replace. Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences. -1 (the default value) means replace all occurrences.
@ -2273,47 +2262,40 @@ PyDoc_STRVAR(bytearray_replace__doc__,
{"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__},
static PyObject * static PyObject *
bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count); bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count);
static PyObject * static PyObject *
bytearray_replace(PyByteArrayObject *self, PyObject *args) bytearray_replace(PyByteArrayObject *self, PyObject *args)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *old; Py_buffer old = {NULL, NULL};
PyObject *new; Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1; Py_ssize_t count = -1;
if (!PyArg_ParseTuple(args, if (!PyArg_ParseTuple(args,
"OO|n:replace", "y*y*|n:replace",
&old, &new, &count)) &old, &new, &count))
goto exit; goto exit;
return_value = bytearray_replace_impl(self, old, new, count); return_value = bytearray_replace_impl(self, &old, &new, count);
exit: exit:
/* Cleanup for old */
if (old.obj)
PyBuffer_Release(&old);
/* Cleanup for new */
if (new.obj)
PyBuffer_Release(&new);
return return_value; return return_value;
} }
static PyObject * static PyObject *
bytearray_replace_impl(PyByteArrayObject *self, PyObject *old, PyObject *new, Py_ssize_t count) bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count)
/*[clinic end generated code: output=4d2e3c9130da0f96 input=9aaaa123608dfc1f]*/ /*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/
{ {
PyObject *res; return (PyObject *)replace((PyByteArrayObject *) self,
Py_buffer vold, vnew; old->buf, old->len,
new->buf, new->len, count);
if (_getbuffer(old, &vold) < 0)
return NULL;
if (_getbuffer(new, &vnew) < 0) {
PyBuffer_Release(&vold);
return NULL;
}
res = (PyObject *)replace((PyByteArrayObject *) self,
vold.buf, vold.len,
vnew.buf, vnew.len, count);
PyBuffer_Release(&vold);
PyBuffer_Release(&vnew);
return res;
} }
/*[clinic input] /*[clinic input]
@ -2383,7 +2365,7 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit
if (sep == Py_None) if (sep == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(sep, &vsub) < 0) if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
n = vsub.len; n = vsub.len;
@ -2566,7 +2548,7 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxspli
if (sep == Py_None) if (sep == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(sep, &vsub) < 0) if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
n = vsub.len; n = vsub.len;
@ -3088,7 +3070,7 @@ bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes)
byteslen = 6; byteslen = 6;
} }
else { else {
if (_getbuffer(bytes, &vbytes) < 0) if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
bytesptr = (char *) vbytes.buf; bytesptr = (char *) vbytes.buf;
byteslen = vbytes.len; byteslen = vbytes.len;
@ -3159,7 +3141,7 @@ bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes)
byteslen = 6; byteslen = 6;
} }
else { else {
if (_getbuffer(bytes, &vbytes) < 0) if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
bytesptr = (char *) vbytes.buf; bytesptr = (char *) vbytes.buf;
byteslen = vbytes.len; byteslen = vbytes.len;
@ -3227,7 +3209,7 @@ bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes)
byteslen = 6; byteslen = 6;
} }
else { else {
if (_getbuffer(bytes, &vbytes) < 0) if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
bytesptr = (char *) vbytes.buf; bytesptr = (char *) vbytes.buf;
byteslen = vbytes.len; byteslen = vbytes.len;

View File

@ -363,59 +363,27 @@ 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\ 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."); 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,
"a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name);
return -1;
}
if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
return -1;
return view->len;
}
PyObject * PyObject *
_Py_bytes_maketrans(PyObject *frm, PyObject *to) _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
{ {
PyObject *res = NULL; PyObject *res = NULL;
Py_buffer bfrm, bto;
Py_ssize_t i; Py_ssize_t i;
char *p; char *p;
bfrm.len = -1; if (frm->len != to->len) {
bto.len = -1;
if (_getbuffer(frm, &bfrm) < 0)
return NULL;
if (_getbuffer(to, &bto) < 0)
goto done;
if (bfrm.len != bto.len) {
PyErr_Format(PyExc_ValueError, PyErr_Format(PyExc_ValueError,
"maketrans arguments must have same length"); "maketrans arguments must have same length");
goto done; return NULL;
} }
res = PyBytes_FromStringAndSize(NULL, 256); res = PyBytes_FromStringAndSize(NULL, 256);
if (!res) { if (!res)
goto done; return NULL;
}
p = PyBytes_AS_STRING(res); p = PyBytes_AS_STRING(res);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
p[i] = (char) i; p[i] = (char) i;
for (i = 0; i < bfrm.len; i++) { for (i = 0; i < frm->len; i++) {
p[((unsigned char *)bfrm.buf)[i]] = ((char *)bto.buf)[i]; p[((unsigned char *)frm->buf)[i]] = ((char *)to->buf)[i];
} }
done:
if (bfrm.len != -1)
PyBuffer_Release(&bfrm);
if (bto.len != -1)
PyBuffer_Release(&bto);
return res; return res;
} }

View File

@ -12,33 +12,6 @@ class bytes "PyBytesObject*" "&PyBytes_Type"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/
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,
"a bytes-like object is required, not '%.100s'",
Py_TYPE(obj)->tp_name);
return -1;
}
if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
return -1;
return view->len;
}
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
Py_ssize_t null_strings, one_strings; Py_ssize_t null_strings, one_strings;
#endif #endif
@ -1349,8 +1322,8 @@ bytes_concat(PyObject *a, PyObject *b)
va.len = -1; va.len = -1;
vb.len = -1; vb.len = -1;
if (_getbuffer(a, &va) < 0 || if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
_getbuffer(b, &vb) < 0) { PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
goto done; goto done;
@ -1448,7 +1421,7 @@ bytes_contains(PyObject *self, PyObject *arg)
Py_buffer varg; Py_buffer varg;
Py_ssize_t pos; Py_ssize_t pos;
PyErr_Clear(); PyErr_Clear();
if (_getbuffer(arg, &varg) < 0) if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
return -1; return -1;
pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
varg.buf, varg.len, 0); varg.buf, varg.len, 0);
@ -1737,7 +1710,7 @@ bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
maxsplit = PY_SSIZE_T_MAX; maxsplit = PY_SSIZE_T_MAX;
if (sep == Py_None) if (sep == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(sep, &vsub) < 0) if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
n = vsub.len; n = vsub.len;
@ -1751,7 +1724,7 @@ bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
bytes.partition bytes.partition
self: self(type="PyBytesObject *") self: self(type="PyBytesObject *")
sep: object sep: Py_buffer
/ /
Partition the bytes into three parts using the given separator. Partition the bytes into three parts using the given separator.
@ -1778,26 +1751,39 @@ PyDoc_STRVAR(bytes_partition__doc__,
"object and two empty bytes objects."); "object and two empty bytes objects.");
#define BYTES_PARTITION_METHODDEF \ #define BYTES_PARTITION_METHODDEF \
{"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__}, {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__},
static PyObject * static PyObject *
bytes_partition(PyBytesObject *self, PyObject *sep) bytes_partition_impl(PyBytesObject *self, Py_buffer *sep);
/*[clinic end generated code: output=b41e119c873c08bc input=6c5b9dcc5a9fd62e]*/
static PyObject *
bytes_partition(PyBytesObject *self, PyObject *args)
{ {
const char *sep_chars; PyObject *return_value = NULL;
Py_ssize_t sep_len; Py_buffer sep = {NULL, NULL};
if (PyBytes_Check(sep)) { if (!PyArg_ParseTuple(args,
sep_chars = PyBytes_AS_STRING(sep); "y*:partition",
sep_len = PyBytes_GET_SIZE(sep); &sep))
} goto exit;
else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) return_value = bytes_partition_impl(self, &sep);
return NULL;
exit:
/* Cleanup for sep */
if (sep.obj)
PyBuffer_Release(&sep);
return return_value;
}
static PyObject *
bytes_partition_impl(PyBytesObject *self, Py_buffer *sep)
/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/
{
return stringlib_partition( return stringlib_partition(
(PyObject*) self, (PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
sep, sep_chars, sep_len sep->obj, (const char *)sep->buf, sep->len
); );
} }
@ -1805,7 +1791,7 @@ bytes_partition(PyBytesObject *self, PyObject *sep)
bytes.rpartition bytes.rpartition
self: self(type="PyBytesObject *") self: self(type="PyBytesObject *")
sep: object sep: Py_buffer
/ /
Partition the bytes into three parts using the given separator. Partition the bytes into three parts using the given separator.
@ -1832,26 +1818,39 @@ PyDoc_STRVAR(bytes_rpartition__doc__,
"objects and the original bytes object."); "objects and the original bytes object.");
#define BYTES_RPARTITION_METHODDEF \ #define BYTES_RPARTITION_METHODDEF \
{"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__}, {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__},
static PyObject * static PyObject *
bytes_rpartition(PyBytesObject *self, PyObject *sep) bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep);
/*[clinic end generated code: output=3a620803657196ee input=79bc2932e78e5ce0]*/
static PyObject *
bytes_rpartition(PyBytesObject *self, PyObject *args)
{ {
const char *sep_chars; PyObject *return_value = NULL;
Py_ssize_t sep_len; Py_buffer sep = {NULL, NULL};
if (PyBytes_Check(sep)) { if (!PyArg_ParseTuple(args,
sep_chars = PyBytes_AS_STRING(sep); "y*:rpartition",
sep_len = PyBytes_GET_SIZE(sep); &sep))
} goto exit;
else if (PyObject_AsCharBuffer(sep, &sep_chars, &sep_len)) return_value = bytes_rpartition_impl(self, &sep);
return NULL;
exit:
/* Cleanup for sep */
if (sep.obj)
PyBuffer_Release(&sep);
return return_value;
}
static PyObject *
bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep)
/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/
{
return stringlib_rpartition( return stringlib_rpartition(
(PyObject*) self, (PyObject*) self,
PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
sep, sep_chars, sep_len sep->obj, (const char *)sep->buf, sep->len
); );
} }
@ -1916,7 +1915,7 @@ bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
maxsplit = PY_SSIZE_T_MAX; maxsplit = PY_SSIZE_T_MAX;
if (sep == Py_None) if (sep == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (_getbuffer(sep, &vsub) < 0) if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
n = vsub.len; n = vsub.len;
@ -2003,7 +2002,7 @@ bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
return -2; return -2;
if (subobj) { if (subobj) {
if (_getbuffer(subobj, &subbuf) < 0) if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
return -2; return -2;
sub = subbuf.buf; sub = subbuf.buf;
@ -2118,7 +2117,7 @@ do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj)
Py_ssize_t seplen; Py_ssize_t seplen;
Py_ssize_t i, j; Py_ssize_t i, j;
if (_getbuffer(sepobj, &vsep) < 0) if (PyObject_GetBuffer(sepobj, &vsep, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sep = vsep.buf; sep = vsep.buf;
seplen = vsep.len; seplen = vsep.len;
@ -2360,7 +2359,7 @@ bytes_count(PyBytesObject *self, PyObject *args)
return NULL; return NULL;
if (sub_obj) { if (sub_obj) {
if (_getbuffer(sub_obj, &vsub) < 0) if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
return NULL; return NULL;
sub = vsub.buf; sub = vsub.buf;
@ -2450,6 +2449,8 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
/*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/ /*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/
{ {
char *input, *output; char *input, *output;
Py_buffer table_view = {NULL, NULL};
Py_buffer del_table_view = {NULL, NULL};
const char *table_chars; const char *table_chars;
Py_ssize_t i, c, changed = 0; Py_ssize_t i, c, changed = 0;
PyObject *input_obj = (PyObject*)self; PyObject *input_obj = (PyObject*)self;
@ -2466,12 +2467,17 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
table_chars = NULL; table_chars = NULL;
tablen = 256; tablen = 256;
} }
else if (PyObject_AsCharBuffer(table, &table_chars, &tablen)) else {
return NULL; if (PyObject_GetBuffer(table, &table_view, PyBUF_SIMPLE) != 0)
return NULL;
table_chars = table_view.buf;
tablen = table_view.len;
}
if (tablen != 256) { if (tablen != 256) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"translation table must be 256 characters long"); "translation table must be 256 characters long");
PyBuffer_Release(&table_view);
return NULL; return NULL;
} }
@ -2480,8 +2486,14 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
del_table_chars = PyBytes_AS_STRING(deletechars); del_table_chars = PyBytes_AS_STRING(deletechars);
dellen = PyBytes_GET_SIZE(deletechars); dellen = PyBytes_GET_SIZE(deletechars);
} }
else if (PyObject_AsCharBuffer(deletechars, &del_table_chars, &dellen)) else {
return NULL; if (PyObject_GetBuffer(deletechars, &del_table_view, PyBUF_SIMPLE) != 0) {
PyBuffer_Release(&table_view);
return NULL;
}
del_table_chars = del_table_view.buf;
dellen = del_table_view.len;
}
} }
else { else {
del_table_chars = NULL; del_table_chars = NULL;
@ -2490,8 +2502,11 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
inlen = PyBytes_GET_SIZE(input_obj); inlen = PyBytes_GET_SIZE(input_obj);
result = PyBytes_FromStringAndSize((char *)NULL, inlen); result = PyBytes_FromStringAndSize((char *)NULL, inlen);
if (result == NULL) if (result == NULL) {
PyBuffer_Release(&del_table_view);
PyBuffer_Release(&table_view);
return NULL; return NULL;
}
output_start = output = PyBytes_AsString(result); output_start = output = PyBytes_AsString(result);
input = PyBytes_AS_STRING(input_obj); input = PyBytes_AS_STRING(input_obj);
@ -2502,11 +2517,14 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
if (Py_CHARMASK((*output++ = table_chars[c])) != c) if (Py_CHARMASK((*output++ = table_chars[c])) != c)
changed = 1; changed = 1;
} }
if (changed || !PyBytes_CheckExact(input_obj)) if (!changed && PyBytes_CheckExact(input_obj)) {
return result; Py_INCREF(input_obj);
Py_DECREF(result); Py_DECREF(result);
Py_INCREF(input_obj); result = input_obj;
return input_obj; }
PyBuffer_Release(&del_table_view);
PyBuffer_Release(&table_view);
return result;
} }
if (table_chars == NULL) { if (table_chars == NULL) {
@ -2516,9 +2534,11 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table_chars[i]); trans_table[i] = Py_CHARMASK(table_chars[i]);
} }
PyBuffer_Release(&table_view);
for (i = 0; i < dellen; i++) for (i = 0; i < dellen; i++)
trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1; trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1;
PyBuffer_Release(&del_table_view);
for (i = inlen; --i >= 0; ) { for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++); c = Py_CHARMASK(*input++);
@ -2544,8 +2564,8 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, Py
@staticmethod @staticmethod
bytes.maketrans bytes.maketrans
frm: object frm: Py_buffer
to: object to: Py_buffer
/ /
Return a translation table useable for the bytes or bytearray translate method. Return a translation table useable for the bytes or bytearray translate method.
@ -2571,28 +2591,35 @@ PyDoc_STRVAR(bytes_maketrans__doc__,
{"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__}, {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__},
static PyObject * static PyObject *
bytes_maketrans_impl(PyObject *frm, PyObject *to); bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to);
static PyObject * static PyObject *
bytes_maketrans(void *null, PyObject *args) bytes_maketrans(void *null, PyObject *args)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *frm; Py_buffer frm = {NULL, NULL};
PyObject *to; Py_buffer to = {NULL, NULL};
if (!PyArg_UnpackTuple(args, "maketrans", if (!PyArg_ParseTuple(args,
2, 2, "y*y*:maketrans",
&frm, &to)) &frm, &to))
goto exit; goto exit;
return_value = bytes_maketrans_impl(frm, to); return_value = bytes_maketrans_impl(&frm, &to);
exit: exit:
/* Cleanup for frm */
if (frm.obj)
PyBuffer_Release(&frm);
/* Cleanup for to */
if (to.obj)
PyBuffer_Release(&to);
return return_value; return return_value;
} }
static PyObject * static PyObject *
bytes_maketrans_impl(PyObject *frm, PyObject *to) bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to)
/*[clinic end generated code: output=89a3c3556975e466 input=d204f680f85da382]*/ /*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/
{ {
return _Py_bytes_maketrans(frm, to); return _Py_bytes_maketrans(frm, to);
} }
@ -3093,8 +3120,8 @@ replace(PyBytesObject *self,
/*[clinic input] /*[clinic input]
bytes.replace bytes.replace
old: object old: Py_buffer
new: object new: Py_buffer
count: Py_ssize_t = -1 count: Py_ssize_t = -1
Maximum number of occurrences to replace. Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences. -1 (the default value) means replace all occurrences.
@ -3123,50 +3150,40 @@ PyDoc_STRVAR(bytes_replace__doc__,
{"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__},
static PyObject * static PyObject *
bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count); bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count);
static PyObject * static PyObject *
bytes_replace(PyBytesObject*self, PyObject *args) bytes_replace(PyBytesObject*self, PyObject *args)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *old; Py_buffer old = {NULL, NULL};
PyObject *new; Py_buffer new = {NULL, NULL};
Py_ssize_t count = -1; Py_ssize_t count = -1;
if (!PyArg_ParseTuple(args, if (!PyArg_ParseTuple(args,
"OO|n:replace", "y*y*|n:replace",
&old, &new, &count)) &old, &new, &count))
goto exit; goto exit;
return_value = bytes_replace_impl(self, old, new, count); return_value = bytes_replace_impl(self, &old, &new, count);
exit: exit:
/* Cleanup for old */
if (old.obj)
PyBuffer_Release(&old);
/* Cleanup for new */
if (new.obj)
PyBuffer_Release(&new);
return return_value; return return_value;
} }
static PyObject * static PyObject *
bytes_replace_impl(PyBytesObject*self, PyObject *old, PyObject *new, Py_ssize_t count) bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count)
/*[clinic end generated code: output=14ce72f4f9cb91cf input=d3ac254ea50f4ac1]*/ /*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/
{ {
const char *old_s, *new_s;
Py_ssize_t old_len, new_len;
if (PyBytes_Check(old)) {
old_s = PyBytes_AS_STRING(old);
old_len = PyBytes_GET_SIZE(old);
}
else if (PyObject_AsCharBuffer(old, &old_s, &old_len))
return NULL;
if (PyBytes_Check(new)) {
new_s = PyBytes_AS_STRING(new);
new_len = PyBytes_GET_SIZE(new);
}
else if (PyObject_AsCharBuffer(new, &new_s, &new_len))
return NULL;
return (PyObject *)replace((PyBytesObject *) self, return (PyObject *)replace((PyBytesObject *) self,
old_s, old_len, (const char *)old->buf, old->len,
new_s, new_len, count); (const char *)new->buf, new->len, count);
} }
/** End DALKE **/ /** End DALKE **/
@ -3181,6 +3198,7 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
{ {
Py_ssize_t len = PyBytes_GET_SIZE(self); Py_ssize_t len = PyBytes_GET_SIZE(self);
Py_ssize_t slen; Py_ssize_t slen;
Py_buffer sub_view = {NULL, NULL};
const char* sub; const char* sub;
const char* str; const char* str;
@ -3188,8 +3206,12 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
sub = PyBytes_AS_STRING(substr); sub = PyBytes_AS_STRING(substr);
slen = PyBytes_GET_SIZE(substr); slen = PyBytes_GET_SIZE(substr);
} }
else if (PyObject_AsCharBuffer(substr, &sub, &slen)) else {
return -1; if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
return -1;
sub = sub_view.buf;
slen = sub_view.len;
}
str = PyBytes_AS_STRING(self); str = PyBytes_AS_STRING(self);
ADJUST_INDICES(start, end, len); ADJUST_INDICES(start, end, len);
@ -3197,17 +3219,25 @@ _bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
if (direction < 0) { if (direction < 0) {
/* startswith */ /* startswith */
if (start+slen > len) if (start+slen > len)
return 0; goto notfound;
} else { } else {
/* endswith */ /* endswith */
if (end-start < slen || start > len) if (end-start < slen || start > len)
return 0; goto notfound;
if (end-slen > start) if (end-slen > start)
start = end - slen; start = end - slen;
} }
if (end-start >= slen) if (end-start < slen)
return ! memcmp(str+start, sub, 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; return 0;
} }
@ -3978,7 +4008,7 @@ PyBytes_Concat(PyObject **pv, PyObject *w)
Py_buffer wb; Py_buffer wb;
wb.len = -1; wb.len = -1;
if (_getbuffer(w, &wb) < 0) { if (PyObject_GetBuffer(w, &wb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name); Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name);
Py_CLEAR(*pv); Py_CLEAR(*pv);

View File

@ -767,6 +767,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
int got_bracket=0; int got_bracket=0;
PyObject *s_buffer = NULL; PyObject *s_buffer = NULL;
Py_ssize_t len; Py_ssize_t len;
Py_buffer view = {NULL, NULL};
if (PyUnicode_Check(v)) { if (PyUnicode_Check(v)) {
s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v); s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
@ -776,7 +777,11 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (s == NULL) if (s == NULL)
goto error; 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, PyErr_Format(PyExc_TypeError,
"complex() argument must be a string or a number, not '%.200s'", "complex() argument must be a string or a number, not '%.200s'",
Py_TYPE(v)->tp_name); Py_TYPE(v)->tp_name);
@ -890,6 +895,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (s-start != len) if (s-start != len)
goto parse_error; goto parse_error;
PyBuffer_Release(&view);
Py_XDECREF(s_buffer); Py_XDECREF(s_buffer);
return complex_subtype_from_doubles(type, x, y); return complex_subtype_from_doubles(type, x, y);
@ -897,6 +903,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string"); "complex() arg is a malformed string");
error: error:
PyBuffer_Release(&view);
Py_XDECREF(s_buffer); Py_XDECREF(s_buffer);
return NULL; return NULL;
} }

View File

@ -1922,8 +1922,6 @@ static int
UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyUnicodeErrorObject *ude; PyUnicodeErrorObject *ude;
const char *data;
Py_ssize_t size;
if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
return -1; return -1;
@ -1944,21 +1942,27 @@ UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1; 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->encoding);
Py_INCREF(ude->object);
Py_INCREF(ude->reason); 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; return 0;
error:
Py_CLEAR(ude->encoding);
Py_CLEAR(ude->object);
Py_CLEAR(ude->reason);
return -1;
} }
static PyObject * static PyObject *

View File

@ -131,6 +131,7 @@ PyFloat_FromString(PyObject *v)
double x; double x;
PyObject *s_buffer = NULL; PyObject *s_buffer = NULL;
Py_ssize_t len; Py_ssize_t len;
Py_buffer view = {NULL, NULL};
PyObject *result = NULL; PyObject *result = NULL;
if (PyUnicode_Check(v)) { if (PyUnicode_Check(v)) {
@ -143,7 +144,11 @@ PyFloat_FromString(PyObject *v)
return NULL; 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, PyErr_Format(PyExc_TypeError,
"float() argument must be a string or a number, not '%.200s'", "float() argument must be a string or a number, not '%.200s'",
Py_TYPE(v)->tp_name); Py_TYPE(v)->tp_name);
@ -170,6 +175,7 @@ PyFloat_FromString(PyObject *v)
else else
result = PyFloat_FromDouble(x); result = PyFloat_FromDouble(x);
PyBuffer_Release(&view);
Py_XDECREF(s_buffer); Py_XDECREF(s_buffer);
return result; return result;
} }

View File

@ -58,7 +58,14 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable)
for (i = 0, nbufs = 0; i < seqlen; i++) { for (i = 0, nbufs = 0; i < seqlen; i++) {
Py_ssize_t itemlen; Py_ssize_t itemlen;
item = PySequence_Fast_GET_ITEM(seq, i); 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, PyErr_Format(PyExc_TypeError,
"sequence item %zd: expected a bytes-like object, " "sequence item %zd: expected a bytes-like object, "
"%.80s found", "%.80s found",

View File

@ -723,10 +723,10 @@ builtin_chr_impl(PyModuleDef *module, int i)
} }
static char * static const char *
source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) 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; Py_ssize_t size;
if (PyUnicode_Check(cmd)) { if (PyUnicode_Check(cmd)) {
@ -735,19 +735,21 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf)
if (str == NULL) if (str == NULL)
return 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, PyErr_Format(PyExc_TypeError,
"%s() arg 1 must be a %s object", "%s() arg 1 must be a %s object",
funcname, what); funcname, what);
return NULL; return NULL;
} }
else if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) {
return NULL;
}
if (strlen(str) != (size_t)size) { if (strlen(str) != (size_t)size) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"source code string cannot contain null bytes"); "source code string cannot contain null bytes");
PyBuffer_Release(view);
return NULL; return NULL;
} }
return str; return str;
@ -827,7 +829,8 @@ static PyObject *
builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize)
/*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/ /*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/
{ {
char *str; Py_buffer view = {NULL, NULL};
const char *str;
int compile_mode = -1; int compile_mode = -1;
int is_ast; int is_ast;
PyCompilerFlags cf; PyCompilerFlags cf;
@ -898,11 +901,12 @@ builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename,
goto finally; goto finally;
} }
str = source_as_string(source, "compile", "string, bytes or AST", &cf); str = source_as_string(source, "compile", "string, bytes or AST", &cf, &view);
if (str == NULL) if (str == NULL)
goto error; goto error;
result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize); result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize);
PyBuffer_Release(&view);
goto finally; goto finally;
error: error:
@ -1042,7 +1046,8 @@ builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyOb
/*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/ /*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/
{ {
PyObject *result, *tmp = NULL; PyObject *result, *tmp = NULL;
char *str; Py_buffer view = {NULL, NULL};
const char *str;
PyCompilerFlags cf; PyCompilerFlags cf;
if (locals != Py_None && !PyMapping_Check(locals)) { if (locals != Py_None && !PyMapping_Check(locals)) {
@ -1089,7 +1094,7 @@ builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyOb
} }
cf.cf_flags = PyCF_SOURCE_IS_UTF8; cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = source_as_string(source, "eval", "string, bytes or code", &cf); str = source_as_string(source, "eval", "string, bytes or code", &cf, &view);
if (str == NULL) if (str == NULL)
return NULL; return NULL;
@ -1098,6 +1103,7 @@ builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyOb
(void)PyEval_MergeCompilerFlags(&cf); (void)PyEval_MergeCompilerFlags(&cf);
result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);
PyBuffer_Release(&view);
Py_XDECREF(tmp); Py_XDECREF(tmp);
return result; return result;
} }
@ -1204,11 +1210,12 @@ builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyOb
v = PyEval_EvalCode(source, globals, locals); v = PyEval_EvalCode(source, globals, locals);
} }
else { else {
char *str; Py_buffer view = {NULL, NULL};
const char *str;
PyCompilerFlags cf; PyCompilerFlags cf;
cf.cf_flags = PyCF_SOURCE_IS_UTF8; cf.cf_flags = PyCF_SOURCE_IS_UTF8;
str = source_as_string(source, "exec", str = source_as_string(source, "exec",
"string, bytes or code", &cf); "string, bytes or code", &cf, &view);
if (str == NULL) if (str == NULL)
return NULL; return NULL;
if (PyEval_MergeCompilerFlags(&cf)) if (PyEval_MergeCompilerFlags(&cf))
@ -1216,6 +1223,7 @@ builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyOb
locals, &cf); locals, &cf);
else else
v = PyRun_String(str, Py_file_input, globals, locals); v = PyRun_String(str, Py_file_input, globals, locals);
PyBuffer_Release(&view);
} }
if (v == NULL) if (v == NULL)
return NULL; return NULL;