Bug #81688 [Asn]: PDO_ODBC doesn't handle fixed-length character columns with character conversio

From: Date: Tue, 14 Dec 2021 13:47:41 +0000
Subject: Bug #81688 [Asn]: PDO_ODBC doesn't handle fixed-length character columns with character conversio
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-238396@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=81688&edit=1 ID: 81688 Updated by: cmb@php.net Reported by: calvin at cmpct dot info Summary: PDO_ODBC doesn't handle fixed-length character columns with character conversio Status: Assigned Type: Bug Package: PDO ODBC Operating System: IBM i 7.2 PHP Version: 8.0.13 Assigned To: cmb Block user comment: N Private report: N New Comment: Oh, forgot: could you also please check the results of the queries with ext/odbc (i.e. the odbc_*() functions)? The implementation is quite different from PDO_ODBC. Previous Comments: ------------------------------------------------------------------------ [2021-12-14 13:11:03] cmb@php.net > Of course, the link to the Appendix isn't any more enlightening: Yeah. :( Anyhow, all this looks remotely related to bug #79059; see particularly my last comment there[1]. It might be worthwhile to try to run the scripts with PDO::ODBC_ATTR_ASSUME_UTF8 set to true, even though that is not yet consistently implemented. [1] <https://bugs.php.net/bug.php?id=79059#1601993047> ------------------------------------------------------------------------ [2021-12-07 16:54:56] calvin at cmpct dot info Interesting observation: if you try to cast so PHP picks a bigger buffer size that might be able to accommodate the conversion, you still get garbage at the end: i.e. select cast(x as char(150)) as X from calvin.bigchars gets you ``` Record string(180) "éééééééééééééééééééééééééééééé 0 (*Wind!@.0*) Gecko* " Record string(165) "ééééééééééééééé 0 (*Windo" Record string(155) "ééééé 0 (*" ``` (I'm guessing that's garbage in memory left over from parsing browscap, since this is CLI...) ------------------------------------------------------------------------ [2021-12-07 16:13:58] kadler at us dot ibm dot com I know my colleague has done some investigation here as to how different databases/drivers react when running in different encodings between the database and the client. IIRC most drivers don't do any conversion and just give back the data in the original encoding (which works "ok" for the most part when everyone is some ASCII variant, but not so when one is EBCDIC). As to how the PHP code works using SQL_DESC_DISPLAY_SIZE, this is the docs: https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlcolattribute-function?view=sql-server-ver15 "SQL_DESC_DISPLAY_SIZE - Maximum number of characters required to display data from the column. For more information about display size, see Column Size, Decimal Digits, Transfer Octet Length, and Display Size in Appendix D: Data Types." Of course, the link to the Appendix isn't any more enlightening: https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/column-size-decimal-digits-transfer-octet-length-and-display-size?view=sql-server-ver15 "The display size value for all data types corresponds to the value in a single descriptor field, SQL_DESC_DISPLAY_SIZE." In the straightforward reading of the spec, I suppose one could argue that the driver should account for any encoding conversion of the data that it will do. ------------------------------------------------------------------------ [2021-12-03 19:05:15] calvin at cmpct dot info I agree overallocation is ugly and something we want to avoid if we can help it. SQL_DESC_OCTET_LENGTH is the same as the display length for the column (in this case, 30) when I write a program to confirm this in C. I'm guessing this is technically correct because it's what it's true for how the database may be representing it, but not after the driver does conversion for the client's encoding. My comment about the overflow is more about how there's garbage at the end there; I suspect it's more not truncating and letting it go out reading stuff in the abyss. Or I'm also reading the situation wrong, and it's reallocating the buffer, just not doing it correctly in a way that leaves garbage. Orrrrrrr the driver isn't truncating properly; either way, I'll probably bug the IBM people responsible for the driver and get their read on the situation. (Apologies if you see dupes, bugs.php keeps timing out...) ------------------------------------------------------------------------ [2021-12-03 18:03:22] cmb@php.net Well, the relevant differenec to the Node ODBC library is apparently that PDO does not rely on SQLDescribeCol() to detect the size, but rather on SQLColAttribute(SQL_DESC_DISPLAY_SIZE)[1]. Whether that is *supposed* to return the "correct" length is not clear to me. Could you please check what SQLColAttribute(SQL_DESC_OCTET_LENGTH) would yield? Might be the same value as SQL_DESC_DISPLAY_SIZE, but maybe not. > there's seemingly a possibility of a buffer overflow I don't think that is possible, since the buffer size is passed to SQLBindCol(), so only truncation may happen. Note that I'm not generally against overallocation, but would try to avoid it for the general case. Some setting (not necessarily INI) might be an option. But please check SQL_DESC_OCTET_LENGTH first. [1] <https://github.com/php/php-src/blob/php-8.0.13/ext/pdo_odbc/odbc_stmt.c#L604> ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=81688 -- Edit this bug report at https://bugs.php.net/bug.php?id=81688&edit=1

« previous php.bugs (#238396) next »