Skip to content

Commit 00546bc

Browse files
committed
Fix bug #60616 (odbc_fetch_into returns junk at end of multi-byte char fields)
The ODBC extension did not support WVARCHAR. WVARCHAR ends up being handled by the default handler where vallen is set by the driver to the actual bytes needed for the field. If it is larger than default-lrl then the output is corrupted (reading past the buffer) because the return functions don't expect that to happen. The patch add support to handle WVARCHAR just like a regular VARCHAR.
1 parent 3e167ba commit 00546bc

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

ext/odbc/php_odbc.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,8 @@ PHP_MINIT_FUNCTION(odbc)
780780
REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS);
781781
REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS);
782782
REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
783+
REGISTER_LONG_CONSTANT("SQL_TYPE_WVARCHAR", SQL_TYPE_WVARCHAR, CONST_PERSISTENT | CONST_CS);
784+
REGISTER_LONG_CONSTANT("SQL_TYPE_WLONGVARCHAR", SQL_TYPE_WLONGVARCHAR, CONST_PERSISTENT | CONST_CS);
783785

784786
/*
785787
* SQLSpecialColumns values
@@ -966,6 +968,8 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC)
966968
case SQL_VARBINARY:
967969
case SQL_LONGVARBINARY:
968970
case SQL_LONGVARCHAR:
971+
case SQL_WVARCHAR:
972+
case SQL_WLONGVARCHAR:
969973
result->values[i].value = NULL;
970974
break;
971975

@@ -1724,6 +1728,8 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
17241728
if (result->binmode == 1) {
17251729
sql_c_type = SQL_C_BINARY;
17261730
}
1731+
case SQL_WVARCHAR:
1732+
case SQL_WLONGVARCHAR:
17271733
case SQL_LONGVARCHAR:
17281734
if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
17291735
Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
@@ -1876,6 +1882,8 @@ PHP_FUNCTION(odbc_fetch_into)
18761882
break;
18771883
}
18781884
if (result->binmode == 1) sql_c_type = SQL_C_BINARY;
1885+
case SQL_WVARCHAR:
1886+
case SQL_WLONGVARCHAR:
18791887
case SQL_LONGVARCHAR:
18801888
if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
18811889
Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
@@ -2095,6 +2103,8 @@ PHP_FUNCTION(odbc_result)
20952103
break;
20962104
}
20972105
case SQL_LONGVARCHAR:
2106+
case SQL_WVARCHAR:
2107+
case SQL_WLONGVARCHAR:
20982108
if (IS_SQL_LONG(result->values[field_ind].coltype)) {
20992109
if (result->longreadlen <= 0) {
21002110
break;
@@ -2132,7 +2142,9 @@ PHP_FUNCTION(odbc_result)
21322142
}
21332143
/* Reduce fieldlen by 1 if we have char data. One day we might
21342144
have binary strings... */
2135-
if (result->values[field_ind].coltype == SQL_LONGVARCHAR) {
2145+
if ((result->values[field_ind].coltype == SQL_LONGVARCHAR) ||
2146+
(result->values[field_ind].coltype == SQL_WVARCHAR) ||
2147+
(result->values[field_ind].coltype == SQL_WLONGVARCHAR)) {
21362148
fieldsize -= 1;
21372149
}
21382150
/* Don't duplicate result, saves one emalloc.
@@ -2247,6 +2259,8 @@ PHP_FUNCTION(odbc_result_all)
22472259
break;
22482260
}
22492261
if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
2262+
case SQL_WVARCHAR:
2263+
case SQL_WLONGVARCHAR:
22502264
case SQL_LONGVARCHAR:
22512265
if (IS_SQL_LONG(result->values[i].coltype) &&
22522266
result->longreadlen <= 0) {

ext/odbc/php_odbc_includes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC);
284284

285285
void odbc_sql_error(ODBC_SQL_ERROR_PARAMS);
286286

287-
#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR)
287+
#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR || x == SQL_WVARCHAR || x == SQL_WLONGVARCHAR)
288288
#define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY)
289289

290290
#ifdef ZTS

0 commit comments

Comments
 (0)