[Mono-bugs] [Bug 456234] New: ODBC utf8: incorrect OdbcDataReader.GetValue() result for VARCHAR if byte size >=255

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Wed Dec 3 16:50:22 EST 2008


https://bugzilla.novell.com/show_bug.cgi?id=456234


           Summary: ODBC utf8: incorrect OdbcDataReader.GetValue() result
                    for VARCHAR  if byte size >=255
           Product: Mono: Class Libraries
           Version: 1.9
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: Sys.Data
        AssignedTo: bnc-blr-team-mono at forge.provo.novell.com
        ReportedBy: amc1999 at gmail.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


Created an attachment (id=257867)
 --> (https://bugzilla.novell.com/attachment.cgi?id=257867)
test

Found and fixed for 1.9 version, but 1.9, 2.0, 2.2 and SVN have same code in
that place and, i assume, same bug. Also because OdbcDataReader.GetValue used
by DataSet to get field values bug is applicable here too. 

Description:
------------
OdbcDataReader.GetValue() return incorrect result if:
size of utf8 string >=255 bytes and one of:
- ODBC driver return StrLen_or_IndPtr=SQL_NO_TOTAL from SQLGetData()
- or utf8 multi-byte character falls across 255 internal byte buffer boundary

Steps to reproduce:
-------------------
1. SQL's and ODBC drivers:
IBM DB2 9.x + IBM ODBC driver
PostgreSQL >= 8.2 ODBC driver >= 8.01
MySQL 5.0.x, mysql-connector-ODBC >= 3.51.17 (not 5.xx)
SQLite3 with ODBC driver >= 0.79

2. Create table with VARCHAR >= 255 field and insert test value:
123456789...250chars...123ñç
End of string bytes are:
 [250]=49 [251]=50 [252]=51 [253]=195 [254]=177 [255]=195 [256]=167

CREATE TABLE utf8_255_test(ival INT NOT NULL, sval VARCHAR(300));
INSERT INTO utf8_255_test(ival, sval) VALUES (255,
'1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ñç');

3. Use DataSet or OdbcDataReader to get field value:

SELECT sval FROM utf8_255_test WHERE sval LIKE '%123ñç';

Current result:
---------------
For most of the drivers you'll get:
123456789...250chars...123ç
it is a bug because has no ñ symbol, which falls across the 255 buffer
boundary

Or with SQLite 0.79 ODBC result is:
ç
one single character and there is nothing else.

A variation of the test for SQLite and other drivers which returns
StrLen_or_IndPtr=SQL_NO_TOTAL from SQLGetData() is to insert any
VARCHAR(>=255). Result of SELECT returned by DataSet or OdbcDataReader will be
string tail after 255. For example, 123456789...250chars...1234567 returns 567
only.

>From attached test you'll get:

DSN=psql-tst;UID=tst;PWD=tst;
End of string bytes: [250]=49  [251]=50  [252]=51  [253]=195  [254]=177 
[255]=195  [256]=167  
CREATE TABLE utf8_255_test(ival INT NOT NULL, sval VARCHAR(300)) : -1
INSERT INTO utf8_255_test(ival, sval) VALUES (1, 'test') : 1
INSERT INTO utf8_255_test(ival, sval) VALUES (255,
'1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ñç')
: 1
SELECT ival, sval FROM utf8_255_test ORDER BY 1
Rows.Count=2 Columns.Count=2
ival | sval | 
[0]: 1 | test | 
[1]: 255 |
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ç
| 
SELECT sval FROM utf8_255_test WHERE sval LIKE '%123ñç' :
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ç
----Test FAILED----
DROP TABLE utf8_255_test : -1

Expected result:
----------------

DRIVER=SQLite3;Database=tst.db;
End of string bytes: [250]=49  [251]=50  [252]=51  [253]=195  [254]=177 
[255]=195  [256]=167  
CREATE TABLE utf8_255_test(ival INT NOT NULL, sval VARCHAR(300)) : -1
INSERT INTO utf8_255_test(ival, sval) VALUES (1, 'test') : 1
INSERT INTO utf8_255_test(ival, sval) VALUES (255,
'1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ñç')
: 1
SELECT ival, sval FROM utf8_255_test ORDER BY 1
Rows.Count=2 Columns.Count=2
ival | sval | 
[0]: 1 | test | 
[1]: 255 |
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ñç
| 
SELECT sval FROM utf8_255_test WHERE sval LIKE '%123ñç' :
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123ñç
++++Test passed OK++++
DROP TABLE utf8_255_test : -1

Fixed:
------

1.Use Decoder.GetChars() instead of Encoding.GetString() to maintain bytes
across 255 buffer boundary.
2.Handle SQL_NO_TOTAL as result of SQLGetData(..., SQLLEN *StrLen_or_IndPtr);

Other Issues:
-------------
Similar logic is used for NVARCHAR in OdbcDataReader and it also may need to
use Decoder.GetChars() instead of Encoding.GetString(), but I can not test it.


-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.


More information about the mono-bugs mailing list