Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
6.2.0, 6.3.0
-
None
-
-
f9d002ea20 (qt/qtbase/dev) ee37e7c69a (qt/qtbase/6.4) ee37e7c69a (qt/tqtc-qtbase/6.4) f9d002ea20 (qt/tqtc-qtbase/dev)
Description
Commit 1df974590f19dec7b632d000ab9408a4de6f117a (Qt 6.2+) broke SQLDriver::formatValue of QByteArray fields for the QMYSQL driver.
The previous code used a buffer that was a (variable sized) char array on the stack for formatting, and relied on the NUL termination of the result of mysql_real_escape_string() to have QString::fromUtf8() work properly. The code in question (qsql_mysql.cpp, 1470-1472):
auto escapedSize = mysql_real_escape_string(d->mysql, buffer.data(), ba.data(), ba.size()); .reserve(escapedSize + 3); r = u'\'' + QString::fromUtf8(buffer) + u'\'';
The new code uses a QVarLengthArray, which is initially resized to the maximum required size, but mysql_real_escape_string() doesn't require the max buffer in most cases. Passing that to QString::fromUtf8() will unfortunately use the length of QVarLengthArray, which also contains some uninitialized bytes, and also contains a NUL byte directly after the escaping. Attempting to construct a SQL query with that result will cause MySQL to stop parsing at that NUL byte in the middle of the query, causing that query to fail.
Fix for the issue is to use the length that mysql_real_escape_string() returns and pass that to fromUtf8():
auto escapedSize = mysql_real_escape_string(d->mysql, buffer.data(), ba.data(), ba.size()); r.reserve(escapedSize + 3); r = u'\'' + QString::fromUtf8(buffer.data(), escapedSize) + u'\'';
Attachments
For Gerrit Dashboard: QTBUG-105078 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
422654,7 | MySQL plugin: fix escaping a QByteArray | dev | qt/qtbase | Status: MERGED | +2 | 0 |
423678,2 | MySQL plugin: fix escaping a QByteArray | 6.4 | qt/qtbase | Status: MERGED | +2 | 0 |