diff options
author | Erlend Egeberg Aasland <erlend.aasland@protonmail.com> | 2022-04-30 15:01:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-30 15:01:37 (GMT) |
commit | 9ea9078ec715ffc92c10c61321f3b1184fa3cac9 (patch) | |
tree | e9a3f8c3730b34e3a02a846924ebe766aa5e6f07 /Modules | |
parent | e91dee87edcf6dee5dd78053004d76e5f05456d4 (diff) | |
download | cpython-9ea9078ec715ffc92c10c61321f3b1184fa3cac9.zip cpython-9ea9078ec715ffc92c10c61321f3b1184fa3cac9.tar.gz cpython-9ea9078ec715ffc92c10c61321f3b1184fa3cac9.tar.bz2 |
gh-92019: Make sqlite3.Blob indexing conform with the norm (#92020)
- get index now returns an int
- set index now requires an int in range(0, 256)
Resolves #92019
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_sqlite/blob.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c index 0c57ff8..76d261b 100644 --- a/Modules/_sqlite/blob.c +++ b/Modules/_sqlite/blob.c @@ -120,10 +120,26 @@ blob_seterror(pysqlite_Blob *self, int rc) } static PyObject * -inner_read(pysqlite_Blob *self, Py_ssize_t length, Py_ssize_t offset) +read_single(pysqlite_Blob *self, Py_ssize_t offset) +{ + unsigned char buf = 0; + int rc; + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_blob_read(self->blob, (void *)&buf, 1, (int)offset); + Py_END_ALLOW_THREADS + + if (rc != SQLITE_OK) { + blob_seterror(self, rc); + return NULL; + } + return PyLong_FromUnsignedLong((unsigned long)buf); +} + +static PyObject * +read_multiple(pysqlite_Blob *self, Py_ssize_t length, Py_ssize_t offset) { assert(length <= sqlite3_blob_bytes(self->blob)); - assert(offset <= sqlite3_blob_bytes(self->blob)); + assert(offset < sqlite3_blob_bytes(self->blob)); PyObject *buffer = PyBytes_FromStringAndSize(NULL, length); if (buffer == NULL) { @@ -175,7 +191,12 @@ blob_read_impl(pysqlite_Blob *self, int length) length = max_read_len; } - PyObject *buffer = inner_read(self, length, self->offset); + assert(length >= 0); + if (length == 0) { + return PyBytes_FromStringAndSize(NULL, 0); + } + + PyObject *buffer = read_multiple(self, length, self->offset); if (buffer == NULL) { return NULL; } @@ -387,7 +408,7 @@ subscript_index(pysqlite_Blob *self, PyObject *item) if (i < 0) { return NULL; } - return inner_read(self, 1, i); + return read_single(self, i); } static int @@ -411,9 +432,9 @@ subscript_slice(pysqlite_Blob *self, PyObject *item) } if (step == 1) { - return inner_read(self, len, start); + return read_multiple(self, len, start); } - PyObject *blob = inner_read(self, stop - start, start); + PyObject *blob = read_multiple(self, stop - start, start); if (blob == NULL) { return NULL; } @@ -455,24 +476,29 @@ ass_subscript_index(pysqlite_Blob *self, PyObject *item, PyObject *value) "Blob doesn't support item deletion"); return -1; } + if (!PyLong_Check(value)) { + PyErr_Format(PyExc_TypeError, + "'%s' object cannot be interpreted as an integer", + Py_TYPE(value)->tp_name); + return -1; + } Py_ssize_t i = get_subscript_index(self, item); if (i < 0) { return -1; } - Py_buffer vbuf; - if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0) { - return -1; + long val = PyLong_AsLong(value); + if (val == -1 && PyErr_Occurred()) { + PyErr_Clear(); + val = -1; } - int rc = -1; - if (vbuf.len != 1) { - PyErr_SetString(PyExc_ValueError, "Blob assignment must be a single byte"); - } - else { - rc = inner_write(self, (const char *)vbuf.buf, 1, i); + if (val < 0 || val > 255) { + PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); + return -1; } - PyBuffer_Release(&vbuf); - return rc; + // Downcast to avoid endianness problems. + unsigned char byte = (unsigned char)val; + return inner_write(self, (const void *)&byte, 1, i); } static int @@ -507,7 +533,7 @@ ass_subscript_slice(pysqlite_Blob *self, PyObject *item, PyObject *value) rc = inner_write(self, vbuf.buf, len, start); } else { - PyObject *blob_bytes = inner_read(self, stop - start, start); + PyObject *blob_bytes = read_multiple(self, stop - start, start); if (blob_bytes != NULL) { char *blob_buf = PyBytes_AS_STRING(blob_bytes); for (Py_ssize_t i = 0, j = 0; i < len; i++, j += step) { |