Describe the bug, including details regarding any error messages, version, and platform.
In the Arrow Flight SQL ODBC driver, ODBCConnection::SetConnectAttr decodes
the SQL_ATTR_CURRENT_CATALOG value with the wrong string decoder when the
call arrives through a wide (Unicode / *W) entry point.
// odbc_impl/odbc_connection.cc
case SQL_ATTR_CURRENT_CATALOG: {
std::string catalog;
if (is_unicode) {
SetAttributeUTF8(value, string_length, catalog); // <-- wrong
} else {
SetAttributeSQLWCHAR(value, string_length, catalog); // <-- wrong
}
...
is_unicode selects the buffer width, not "needs conversion":
- A unicode (
SQLSetConnectAttrW) call hands over a wide SQLWCHAR buffer
and must be decoded with SetAttributeSQLWCHAR.
- A non-unicode (
SQLSetConnectAttrA) call hands over a byte string and is
decoded with SetAttributeUTF8.
The two branches are swapped. When a wide catalog name is decoded with the
byte-wise SetAttributeUTF8, the wide buffer is misread: with a null-terminated
(SQL_NTS) length it is truncated at the first embedded NUL of the wide
encoding (e.g. UTF-16 "odbc" → "o"); with an explicit length it is stored
raw, embedded NULs and all (UTF-16 "my_catalog" →
"m\0y\0_\0c\0a\0t\0a\0l\0o\0g\0"). Either way the stored catalog is wrong.
The correct mapping is already established by the getter side: GetStringAttribute
(in attribute_utils.h) maps is_unicode == true to GetAttributeSQLWCHAR.
The setter for SQL_ATTR_CURRENT_CATALOG inverts it.
The same class of bug exists in ODBCDescriptor::SetField for SQL_DESC_NAME,
which unconditionally uses the byte-wise SetAttributeUTF8 even though the
matching getter (GetField / SQL_DESC_NAME) reads the field back with
GetAttributeSQLWCHAR — so the field is stored wide-origin but decoded
byte-wise on the way in.
Impact: an application that sets a multi-character catalog through the
wide entry point gets a corrupted catalog name back, so subsequent catalog
scoping operates on the wrong (or a non-existent) catalog.
Introduced by:
Component(s)
C++, FlightRPC
Describe the bug, including details regarding any error messages, version, and platform.
In the Arrow Flight SQL ODBC driver,
ODBCConnection::SetConnectAttrdecodesthe
SQL_ATTR_CURRENT_CATALOGvalue with the wrong string decoder when thecall arrives through a wide (Unicode /
*W) entry point.is_unicodeselects the buffer width, not "needs conversion":SQLSetConnectAttrW) call hands over a wideSQLWCHARbufferand must be decoded with
SetAttributeSQLWCHAR.SQLSetConnectAttrA) call hands over a byte string and isdecoded with
SetAttributeUTF8.The two branches are swapped. When a wide catalog name is decoded with the
byte-wise
SetAttributeUTF8, the wide buffer is misread: with a null-terminated(
SQL_NTS) length it is truncated at the first embedded NUL of the wideencoding (e.g. UTF-16
"odbc"→"o"); with an explicit length it is storedraw, embedded NULs and all (UTF-16
"my_catalog"→"m\0y\0_\0c\0a\0t\0a\0l\0o\0g\0"). Either way the stored catalog is wrong.The correct mapping is already established by the getter side:
GetStringAttribute(in
attribute_utils.h) mapsis_unicode == truetoGetAttributeSQLWCHAR.The setter for
SQL_ATTR_CURRENT_CATALOGinverts it.The same class of bug exists in
ODBCDescriptor::SetFieldforSQL_DESC_NAME,which unconditionally uses the byte-wise
SetAttributeUTF8even though thematching getter (
GetField/SQL_DESC_NAME) reads the field back withGetAttributeSQLWCHAR— so the field is stored wide-origin but decodedbyte-wise on the way in.
Impact: an application that sets a multi-character catalog through the
wide entry point gets a corrupted catalog name back, so subsequent catalog
scoping operates on the wrong (or a non-existent) catalog.
Introduced by:
SQL_ATTR_CURRENT_CATALOG: swapped from the start in the original driverimport, [C++][FlightRPC] Accept donation of ODBC driver #46522 (GH-46522: [C++][FlightRPC] Add Arrow Flight SQL ODBC driver #40939). The getter was written against the shared
GetStringAttributehelper (correct); the setter open-coded the branch inlineand inverted it.
SQL_DESC_NAME: originally consistent (getter and setter both byte-wise);[C++][FlightRPC][ODBC] SQLColAttribute implementation #47721 (GH-47721: [C++][FlightRPC] Return ODBC Column Attribute from result set #48050) migrated the descriptor string getters to wide
GetAttributeSQLWCHARbut left this setter byte-wise.Component(s)
C++, FlightRPC