Bug #60616 [Asn->Csd]: odbc_fetch_into returns junk data at end of multi-byte char fields
| From: | keyur@php.net | Date: | Wed, 30 Jul 2014 02:57:44 +0000 |
| Subject: | Bug #60616 [Asn->Csd]: odbc_fetch_into returns junk data at end of multi-byte char fields | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-186871@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=60616&edit=1
ID: 60616
Updated by: keyur@php.net
Reported by: j dot faithw at yahoo dot com
Summary: odbc_fetch_into returns junk data at end of
multi-byte char fields
-Status: Assigned
+Status: Closed
Type: Bug
Package: ODBC related
Operating System: Linux
PHP Version: 5.3.8
Assigned To: keyur
Block user comment: N
Private report: N
New Comment:
The fix for this bug has been committed.
Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
For Windows:
http://windows.php.net/snapshots/
Thank you for the report, and for helping us make PHP better.
Thanks for the note! I fixed the problem for CHAR fields as well
(https://github.com/php/php-src/commit/65364fe7d00319f6bfb4814980988d34183f9f78)
Please try and reopen this if it doesn't work.
Previous Comments:
------------------------------------------------------------------------
[2014-07-29 09:45:00] j dot faithw at yahoo dot com
The patch adds support for WVARCHAR which should fix issues with that datatype but this bug was for
the CHAR datatype which is still broken.
------------------------------------------------------------------------
[2014-07-28 23:30:25] keyur@php.net
The fix for this bug has been committed.
Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
For Windows:
http://windows.php.net/snapshots/
Thank you for the report, and for helping us make PHP better.
------------------------------------------------------------------------
[2014-07-28 23:29:06] keyur@php.net
Thank you for your bug report. This issue has already been fixed
in the latest released version of PHP, which you can download at
http://www.php.net/downloads.php
Patch committed to Git https://github.com/php/php-src/commit/00546bc9b7cb8208c27de9c6ebd12156401a5607
------------------------------------------------------------------------
[2011-12-28 11:57:14] j dot faithw at yahoo dot com
Description:
------------
This relates to bug#25792, which has been marked Analyzed but does not seem to be fixed.
When retrieving data from a char() field containing multi-byte characters using e.g.
odbc_fetch_into(), if the number of bytes used exceeds the number of characters then junk data is
returned at the end of the string.
I have experience this with Postgres char columns when the database is created with e.g the EUC_CN
character encoding(createdb -E EUC_CN).
This encoding uses between 1 and 3 bytes per character. So a char(10) could need up to 30 bytes.
The problem is in the odbc_bindcols function in ext/odbc/php_odbc.c
SQLColAttributes is called with SQL_COLUMN_DISPLAY_SIZE but this indicates the maximum number of
characters required not the number of bytes.
This means the buffer allocated for the value may not be big enough
result->values[i].value=(char)emalloc(displaysize+1);
Later on in e.g. odbc_fetch_into
Z_STRLEN_P(tmp) = result->values[i].vallen;
Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp));
This can result in a vallen bigger that displaysize. But the ODBC driver will only fill in at most
displaysize+1 bytes(including null terminator). This means character data is missed and junk bytes
are returned instead.
The same problem may exist in ext/pdo_odbc/odbc_stmt.c. Where
rc = SQLColAttribute(S->stmt, colno+1, SQL_DESC_DISPLAY_SIZE,
NULL, 0, NULL, &displaysize);
is called. But I have not tested this.
The following fixes odbc_bindcols for the char(x) datatype. I believe 4 bytes is the maximum
required for any character encoding.
php_odbc.c:line 988
if (result->values[i].coltype == SQL_CHAR) {
//If using a multibyte character encoding
//number of bytes could be 4*SQL_COLUMN_DISPLAY_SIZE.
//Without this workaround various functions
//e.g. odbc_fetch_into will return data with a null after
//diplaysize bytes and extra junk data at the end as
//vallen can be bigger than displaysize. Tested using
//PostgreSQL with EUC_CN encoding.
displaysize*=4;
}
The fix may be needed for other data types as well as SQL_CHAR.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=60616&edit=1