diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-09-17 06:20:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-17 06:20:56 (GMT) |
commit | f669581a9527afb0d2325f9845a86715c0ba365d (patch) | |
tree | 964f3dd5596e65d33e5349497025b44e070f33b9 /Modules/_sqlite/row.c | |
parent | dfd34a9cd58e8150c324190f746de919e140abe8 (diff) | |
download | cpython-f669581a9527afb0d2325f9845a86715c0ba365d.zip cpython-f669581a9527afb0d2325f9845a86715c0ba365d.tar.gz cpython-f669581a9527afb0d2325f9845a86715c0ba365d.tar.bz2 |
bpo-38185: Fixed case-insensitive string comparison in sqlite3.Row indexing. (GH-16190)
Diffstat (limited to 'Modules/_sqlite/row.c')
-rw-r--r-- | Modules/_sqlite/row.c | 62 |
1 files changed, 31 insertions, 31 deletions
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 758518a..4b47108 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -76,16 +76,38 @@ PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) return item; } +static int +equal_ignore_case(PyObject *left, PyObject *right) +{ + int eq = PyObject_RichCompareBool(left, right, Py_EQ); + if (eq) { /* equal or error */ + return eq; + } + if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) { + return 0; + } + if (!PyUnicode_IS_ASCII(left) || !PyUnicode_IS_ASCII(right)) { + return 0; + } + + Py_ssize_t len = PyUnicode_GET_LENGTH(left); + if (PyUnicode_GET_LENGTH(right) != len) { + return 0; + } + const Py_UCS1 *p1 = PyUnicode_1BYTE_DATA(left); + const Py_UCS1 *p2 = PyUnicode_1BYTE_DATA(right); + for (; len; len--, p1++, p2++) { + if (Py_TOLOWER(*p1) != Py_TOLOWER(*p2)) { + return 0; + } + } + return 1; +} + PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) { Py_ssize_t _idx; - const char *key; Py_ssize_t nitems, i; - const char *compare_key; - - const char *p1; - const char *p2; - PyObject* item; if (PyLong_Check(idx)) { @@ -98,44 +120,22 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) Py_XINCREF(item); return item; } else if (PyUnicode_Check(idx)) { - key = PyUnicode_AsUTF8(idx); - if (key == NULL) - return NULL; - nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { PyObject *obj; obj = PyTuple_GET_ITEM(self->description, i); obj = PyTuple_GET_ITEM(obj, 0); - compare_key = PyUnicode_AsUTF8(obj); - if (!compare_key) { + int eq = equal_ignore_case(idx, obj); + if (eq < 0) { return NULL; } - - p1 = key; - p2 = compare_key; - - while (1) { - if ((*p1 == (char)0) || (*p2 == (char)0)) { - break; - } - - if ((*p1 | 0x20) != (*p2 | 0x20)) { - break; - } - - p1++; - p2++; - } - - if ((*p1 == (char)0) && (*p2 == (char)0)) { + if (eq) { /* found item */ item = PyTuple_GetItem(self->data, i); Py_INCREF(item); return item; } - } PyErr_SetString(PyExc_IndexError, "No item with that key"); |