Skip to content

Commit b034f9c

Browse files
committed
fix length read from app ptr when param binding (#173)
This commit fixes the length handling of received wide-char strings as parameters: the indicator-length pointer of the API call provides the octet count, so the lenght needs to be divided by wide-char size. Besides a couple of tests for the fix, the commit adds a new test on null generation (both of non-NULL and NULL types). (cherry picked from commit 29376ec) Resolve conflicts: - driver/convert.c Unit testing changes have not been ported.
1 parent 6ae0ecd commit b034f9c

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

driver/convert.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,7 +3210,6 @@ static BOOL xstr_to_number(esodbc_stmt_st *stmt, void *data_ptr,
32103210
SQLRETURN c2sql_null(esodbc_rec_st *arec,
32113211
esodbc_rec_st *irec, char *dest, size_t *len)
32123212
{
3213-
assert(irec->concise_type == ESODBC_SQL_NULL);
32143213
if (dest) {
32153214
memcpy(dest, JSON_VAL_NULL, sizeof(JSON_VAL_NULL) - /*\0*/1);
32163215
}
@@ -4121,6 +4120,37 @@ SQLRETURN c2sql_interval(esodbc_rec_st *arec, esodbc_rec_st *irec,
41214120
# undef ASSIGN_SIGNED
41224121
}
41234122

4123+
static inline SQLLEN get_octet_len(SQLLEN *octet_len_ptr, void *data_ptr,
4124+
BOOL wide)
4125+
{
4126+
SQLLEN cnt;
4127+
4128+
assert(data_ptr);
4129+
4130+
if (! octet_len_ptr) {
4131+
/* "If [...] is a null pointer, the driver assumes that all input
4132+
* parameter values are non-NULL and that character and binary data is
4133+
* null-terminated." */
4134+
cnt = wide ? wcslen((wchar_t *)data_ptr) : strlen((char *)data_ptr);
4135+
} else {
4136+
cnt = *octet_len_ptr;
4137+
switch (cnt) {
4138+
case SQL_NTSL:
4139+
cnt = wide ? wcslen((wchar_t *)data_ptr) :
4140+
strlen((char *)data_ptr);
4141+
break;
4142+
case SQL_NULL_DATA:
4143+
BUG("converting SQL_NULL_DATA");
4144+
cnt = -1; /* UTF16/8 will fail */
4145+
break;
4146+
default: /* get characters count from octets count */
4147+
cnt /= wide ? sizeof(SQLWCHAR) : sizeof(SQLCHAR);
4148+
}
4149+
}
4150+
4151+
return cnt;
4152+
}
4153+
41244154
static SQLRETURN c2sql_cstr2qstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
41254155
SQLULEN pos, char *dest, size_t *len)
41264156
{
@@ -4133,7 +4163,7 @@ static SQLRETURN c2sql_cstr2qstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
41334163
/* pointer to app's buffer */
41344164
data_ptr = deferred_address(SQL_DESC_DATA_PTR, pos, arec);
41354165

4136-
cnt = octet_len_ptr ? *octet_len_ptr : strlen((char *)data_ptr);
4166+
cnt = get_octet_len(octet_len_ptr, data_ptr, /*wide*/FALSE);
41374167

41384168
if (dest) {
41394169
*dest = '"';
@@ -4167,7 +4197,7 @@ static SQLRETURN c2sql_wstr2qstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
41674197
/* pointer to app's buffer */
41684198
data_ptr = deferred_address(SQL_DESC_DATA_PTR, pos, arec);
41694199

4170-
cnt = octet_len_ptr ? *octet_len_ptr : wcslen((wchar_t *)data_ptr);
4200+
cnt = get_octet_len(octet_len_ptr, data_ptr, /*wide*/TRUE);
41714201

41724202
if (dest) {
41734203
*dest = '"';
@@ -4186,7 +4216,7 @@ static SQLRETURN c2sql_wstr2qstr(esodbc_rec_st *arec, esodbc_rec_st *irec,
41864216
octets = WCS2U8((wchar_t *)data_ptr, (int)cnt, dest + !!dest,
41874217
dest ? INT_MAX : 0);
41884218
if ((err = GetLastError())) {
4189-
ERRH(stmt, "converting to multibyte string failed: %d", err);
4219+
ERRH(stmt, "converting to multibyte string failed: 0x%x", err);
41904220
RET_HDIAGS(stmt, SQL_STATE_HY000);
41914221
}
41924222
} else {

0 commit comments

Comments
 (0)