From 38277a88f1dd69de6e031bc8313c8d5beadf6bd0 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 8 Nov 2024 13:16:21 +0100 Subject: [PATCH] SQL/ODBC: escape values in connection string The previous attempt to escape invalid characters for username/password did not work for e.g. '}' or '{'. The msdn documentation is somewhat inconsitent here but after testing it looks like putting the username/password inside '{' and '}' no matter if needed or not is the easiest way. We have to escape '}' by doubling it though. No need to escape the DSN - testing on windows revealed that ';' is not allowed in there and '\'' and '"' at the start of the DSN is perfectly fine without any escaping. Pick-to: 6.9 6.8 Fixes: QTBUG-122642 Change-Id: I04d007d343dd65eb0dbc0252518843eb43cd9ab8 Reviewed-by: Axel Spoerl --- src/plugins/sqldrivers/odbc/qsql_odbc.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp index 9a890c044cf..f2f2619404c 100644 --- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp +++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp @@ -1920,18 +1920,6 @@ bool QODBCDriver::open(const QString & db, int, const QString& connOpts) { - const auto ensureEscaped = [](QString arg) -> QString { - QChar quoteChar; - if (arg.startsWith(u'"')) - quoteChar = u'\''; - else if (arg.startsWith(u'\'')) - quoteChar = u'"'; - else if (arg.contains(u';')) - quoteChar = u'"'; - else - return arg; - return quoteChar + arg + quoteChar; - }; Q_D(QODBCDriver); if (isOpen()) close(); @@ -1967,17 +1955,20 @@ bool QODBCDriver::open(const QString & db, QString connQStr; // support the "DRIVER={SQL SERVER};SERVER=blah" syntax if (db.contains(".dsn"_L1, Qt::CaseInsensitive)) - connQStr = "FILEDSN="_L1 + ensureEscaped(db); + connQStr = "FILEDSN="_L1 + db; else if (db.contains("DRIVER="_L1, Qt::CaseInsensitive) || db.contains("SERVER="_L1, Qt::CaseInsensitive)) connQStr = db; else - connQStr = "DSN="_L1 + ensureEscaped(db); + connQStr = "DSN="_L1 + db; + const auto escapeUserPassword = [](QString arg) -> QString { + return u'{' + arg.replace(u'}', u'{') + u'}'; + }; if (!user.isEmpty()) - connQStr += ";UID="_L1 + ensureEscaped(user); + connQStr += ";UID="_L1 + escapeUserPassword(user); if (!password.isEmpty()) - connQStr += ";PWD="_L1 + ensureEscaped(password); + connQStr += ";PWD="_L1 + escapeUserPassword(password); SQLSMALLINT cb; QVarLengthArray connOut(1024);