[php-src] PR #23445: Fix GH-23444: pdo_odbc does not convert Unicode data outside Windows
| From: | lazerg | Date: | Tue, 25 Aug 2026 07:59:06 +0000 |
| Subject: | [php-src] PR #23445: Fix GH-23444: pdo_odbc does not convert Unicode data outside Windows | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-38120@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/23445
Author: lazerg
PDO::ODBC_ATTR_ASSUME_UTF8 binds wide
(SQL_WCHAR/SQL_WVARCHAR) parameters and columns as
SQL_C_BINARY so that pdo_odbc can do the UTF-8 conversion itself. Both halves of that
conversion, pdo_odbc_utf82ucs2() and pdo_odbc_ucs22utf8(), sit inside
#ifdef PHP_WIN32 and are MultiByteToWideChar() calls. Everywhere else they
return PDO_ODBC_CONV_NOT_REQUIRED and nothing is converted, so raw UTF-8 reaches the
server for an nvarchar parameter and raw UTF-16 comes back for an nvarchar
column. With msodbcsql18 a non-ASCII parameter whose byte length is odd is rejected with
HY090.
Both helpers are now plain UTF-8 to UTF-16 conversions with no platform code. The data-at-exec
branch also needed fixing: it declared the unconverted byte length in
SQL_LEN_DATA_AT_EXEC() while SQLPutData() then sent the converted bytes,
which the server rejects with 22026.
Verified against SQL Server 2025 and ODBC Driver 18 through unixODBC 2.3.14 on macOS: parameters,
LIKE patterns and fetched column values all round-trip, including characters outside
the BMP. ext/pdo_odbc/tests is green with that DSN, and unchanged against the SQLite3
ODBC driver.
One thing worth separating out from the report: the N'…' literal inside the
query text in that snippet is mangled before it reaches the server, because unixODBC transcodes the
statement text using the process locale's charset and PHP runs in the C locale. That is a
different problem from the bound parameter and is not addressed here.
Fixes GH-23444