Bug #66943 SQLPutData don't handle UNICODE string with SQL_NTS in string length.
Submitted: 24 Sep 2012 10:24 Modified: 15 Apr 2014 21:45
Reporter: Kirill Lebedev Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / ODBC Severity:S3 (Non-critical)
Version:5.2.2 OS:Any
Assigned to: Bogdan Degtyariov CPU Architecture:Any
Tags: SQLPutData, Unicode

[24 Sep 2012 10:24] Kirill Lebedev
Description:
SQLPutData function work incorrectly with SQL_C_WCHAR data in rgbValue and SQL_NTS in cbValue. cbValue = strlen(rgbValue) gives wrong result.

How to repeat:
SQLPutData(hstmt, L"Data", SQL_NTS);
[24 Oct 2012 8:54] Bogdan Degtyariov
Kirill,

Please note that in some systems such as 64-bit Linux the sizes of SQLWCHAR and wchar_t types are different (in windows they are the same):

 - SQLWCHAR is defined as 16-bit short
 - wchar_t is 32-bit

Therefore using L"data" makes the string that contains the SQLWCHAR termination symbol 0x0000.

UnixODBC headers have a remark about this in sqltypes.h

/* 
 * NOTE: The Microsoft unicode define is only for apps that want to use TCHARs and 
 *  be able to compile for both unicode and non-unicode with the same source.
 *  This is not recommanded for linux applications and is not supported
 * 	by the standard linux string header files.
 */

You have to convert your string from 32-bit characters (wchar_t) to 16-bit characters (SQLWCHAR).

Also, make sure you are using the UNICODE version of Connector/ODBC 5.2 as now it is shipped in two separate packages for ANSI and UNICODE support.

Marking this report as "Not a bug".
[24 Oct 2012 9:40] Kirill Lebedev
Let's speak about windows. In this case SQLWCHAR and wchar_t have the same size. Now let's look at the source. SQLPutdata in execute.c calculate the length of rgbValue in case of cbValue == SQL_NTS through the strlen. strlen(L"Data") == 1 I thing this is Bug, but for some reason you think otherwise.
[24 Oct 2012 10:31] Bogdan Degtyariov
Kirill,

Thanks for your feedback.

strlen() function is safe in that context because all strings are 
converted to UTF8 character set for the internal data processing.
UTF8 charset (unlike UTF16 or UTF32) does not contain 0x00 bytes in 
its characters. Hence strlen() is never run against L"Data".
As I have just mentioned L"Data" is immediately converted to UTF8 
representation of "Data" string, which in that particular case is
identical to 1-byte-per-character Latin1 string.

Please make sure you are working with "MySQL ODBC 5.2w Driver", 
which supports UNICODE (w-driver). 
The effect you have described might be observed when the ANSI 
(a-driver) version "MySQL ODBC 5.2a Driver" is used with UNICODE
data.
[24 Oct 2012 10:57] Kirill Lebedev
SQLPutData is not internal function, this is function exported by driver directly to the user. If user call SQLBindParameter with SQL_C_WCHAR type then he can call SQLPutData with L"Data" (on windows).
[24 Oct 2012 11:14] Bogdan Degtyariov
Kirill,

My apologies, I think you are right.
Specifying the type in SQLBindParameter() is logical.
However, accordingly to this MSDN article we should only treat 
SQL_C_BINARY and SQL_C_CHAR:

http://msdn.microsoft.com/en-us/library/ms713824%28v=vs.85%29.aspx

I need to check with other developers if this should be extended 
for SQL_C_WCHAR too.
[20 Nov 2013 11:56] Hemant Dangi
The patch has been pushed to
5.1 tree revision 1124
5.2 tree revision 1190
5.3 tree revision 1219
[21 Nov 2013 21:53] Daniel So
Added an entry to the Connector/ODBC 5.1.14, 5.2.7, and 5.3.1 changelogs:

"The function SQLPutData() gave an error when handling a Unicode string that had SQL_NTS given as its string length."
[26 Mar 2014 20:58] Daniel So
Reopened bug and last push reverted back.
[15 Apr 2014 18:42] Kirill Lebedev
Commit was reverted but status is still "Closed". What the hell? :-(