summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeyur Govande <keyur@php.net>2014-07-28 23:15:23 +0000
committerKeyur Govande <keyur@php.net>2014-07-28 23:15:23 +0000
commit00546bc9b7cb8208c27de9c6ebd12156401a5607 (patch)
tree39956a5dfd4b05c9e77b0f719ca72c102705bb1f
parent3e167ba990afc1f46739dfed9d4ba42e9389b2f2 (diff)
downloadphp-git-00546bc9b7cb8208c27de9c6ebd12156401a5607.tar.gz
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.
-rw-r--r--ext/odbc/php_odbc.c16
-rw-r--r--ext/odbc/php_odbc_includes.h2
2 files changed, 16 insertions, 2 deletions
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index 4d21b3a136..a6544d31e4 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -780,6 +780,8 @@ PHP_MINIT_FUNCTION(odbc)
REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("SQL_TYPE_WVARCHAR", SQL_TYPE_WVARCHAR, CONST_PERSISTENT | CONST_CS);
+ REGISTER_LONG_CONSTANT("SQL_TYPE_WLONGVARCHAR", SQL_TYPE_WLONGVARCHAR, CONST_PERSISTENT | CONST_CS);
/*
* SQLSpecialColumns values
@@ -966,6 +968,8 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC)
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
case SQL_LONGVARCHAR:
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
result->values[i].value = NULL;
break;
@@ -1724,6 +1728,8 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
if (result->binmode == 1) {
sql_c_type = SQL_C_BINARY;
}
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
case SQL_LONGVARCHAR:
if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
@@ -1876,6 +1882,8 @@ PHP_FUNCTION(odbc_fetch_into)
break;
}
if (result->binmode == 1) sql_c_type = SQL_C_BINARY;
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
case SQL_LONGVARCHAR:
if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
@@ -2095,6 +2103,8 @@ PHP_FUNCTION(odbc_result)
break;
}
case SQL_LONGVARCHAR:
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
if (IS_SQL_LONG(result->values[field_ind].coltype)) {
if (result->longreadlen <= 0) {
break;
@@ -2132,7 +2142,9 @@ PHP_FUNCTION(odbc_result)
}
/* Reduce fieldlen by 1 if we have char data. One day we might
have binary strings... */
- if (result->values[field_ind].coltype == SQL_LONGVARCHAR) {
+ if ((result->values[field_ind].coltype == SQL_LONGVARCHAR) ||
+ (result->values[field_ind].coltype == SQL_WVARCHAR) ||
+ (result->values[field_ind].coltype == SQL_WLONGVARCHAR)) {
fieldsize -= 1;
}
/* Don't duplicate result, saves one emalloc.
@@ -2247,6 +2259,8 @@ PHP_FUNCTION(odbc_result_all)
break;
}
if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
case SQL_LONGVARCHAR:
if (IS_SQL_LONG(result->values[i].coltype) &&
result->longreadlen <= 0) {
diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h
index a9b0acfa0c..b3ae889974 100644
--- a/ext/odbc/php_odbc_includes.h
+++ b/ext/odbc/php_odbc_includes.h
@@ -284,7 +284,7 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC);
void odbc_sql_error(ODBC_SQL_ERROR_PARAMS);
-#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR)
+#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR || x == SQL_WVARCHAR || x == SQL_WLONGVARCHAR)
#define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY)
#ifdef ZTS