]> granicus.if.org Git - php/commitdiff
Fix bug #60616 (odbc_fetch_into returns junk at end of multi-byte char fields)
authorKeyur Govande <keyur@php.net>
Mon, 28 Jul 2014 23:15:23 +0000 (23:15 +0000)
committerKeyur Govande <keyur@php.net>
Mon, 28 Jul 2014 23:15:23 +0000 (23:15 +0000)
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.

ext/odbc/php_odbc.c
ext/odbc/php_odbc_includes.h

index 4d21b3a136774eca2d8246d6b50ce933b2784f6f..a6544d31e4ccf2823b300a22d652331ff1a7cdcf 100644 (file)
@@ -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) {
index a9b0acfa0c5ad591fcfe60610c85dafd36e8dfb7..b3ae88997403e17322dbc0cf395402f5e6987e7e 100644 (file)
@@ -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