Skip to content

Commit bb054a9

Browse files
johannesnmariz
authored andcommitted
BUG28280321: Fix segmentation fault when using unicode characters in tables
With Python 2.7 and use_pure=False, a segmentation fault is raised when using unicode characters in table objects operations. This patch fixes this issue by handling unicode string casts in Python 2. Tests were added for both tables and collections.
1 parent 3fffef5 commit bb054a9

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

src/mysqlxpb/mysqlxpb.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,12 @@ static void AddPyListToMessageRepeatedMessage(
423423
if (list_size > 0) {
424424
mutable_field->Reserve(list_size);
425425
for (Py_ssize_t idx = 0; idx < list_size; ++idx) {
426-
mutable_field->AddAllocated(
427-
CreateMessage(PyList_GetItem(list, idx), factory));
426+
google::protobuf::Message* msg = CreateMessage(PyList_GetItem(list, idx), factory);
427+
if (!msg) {
428+
// CreateMessage already reported an error, we can leave quietly
429+
return;
430+
}
431+
mutable_field->AddAllocated(msg);
428432
}
429433
}
430434
}

src/mysqlxpb/python_cast.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ std::string python_cast<std::string>(PyObject* obj) {
133133
} else if (PyBytes_CheckExact(obj)) {
134134
return std::string(PyBytes_AsString(obj), PyBytes_Size(obj));
135135
}
136+
#else
137+
else if (PyUnicode_CheckExact(obj)) {
138+
PyObject* pystring = PyUnicode_AsUTF8String(obj);
139+
if (pystring) {
140+
std::string result(PyString_AsString(pystring), PyString_Size(pystring));
141+
Py_DECREF(pystring);
142+
return result;
143+
}
144+
}
136145
#endif
137146

138147
THROW_BAD_PYTHON_CAST(std::string);

tests/test_mysqlx_crud.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,11 @@ def test_add(self):
599599
result = collection.find().execute()
600600
self.assertEqual(7, len(result.fetch_all()))
601601

602+
# test unicode
603+
result = collection.add({"age": 1, "name": u"😀"}).execute()
604+
self.assertEqual(result.get_affected_items_count(), 1)
605+
self.assertEqual(8, collection.count())
606+
602607
if tests.MYSQL_VERSION > (8, 0, 4):
603608
# Following test are only possible on servers with id generetion.
604609
# Ensure _id is created at the server side
@@ -2110,6 +2115,12 @@ def test_insert(self):
21102115
rows = result.fetch_all()
21112116
self.assertEqual(6, len(rows))
21122117

2118+
# test unicode
2119+
table.insert("age", "name").values(1, u"😀").execute()
2120+
result = table.select().execute()
2121+
rows = result.fetch_all()
2122+
self.assertEqual(7, len(rows))
2123+
21132124
drop_table(self.schema, "test")
21142125

21152126
def test_update(self):

0 commit comments

Comments
 (0)