]> granicus.if.org Git - php/commitdiff
Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
authorChristoph M. Becker <cmb@php.net>
Thu, 2 Jul 2015 22:04:50 +0000 (00:04 +0200)
committerChristoph M. Becker <cmb@php.net>
Thu, 2 Jul 2015 22:15:47 +0000 (00:15 +0200)
The SQL Server Native Client 11.0 and maybe other ODBC drivers report
NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0. This causes too small a
buffer to be emalloc'd, likely causing a segfault in the following. As we don't
know the real size of the column data, we treat such colums as
SQL_WLONGVARCHAR.

The related bug #67437 suggests that some drivers report a size of ~4GB. It is
not certain that this is really the case (there might be some integer overflow
involved, and anyway, there has been no feedback), so we do not cater for this
now. However, it would not be hard to treat all sizes above a certain threshold
in a similar way, i.e. as SQL_WLONGVARCHAR.

ext/odbc/php_odbc.c
ext/odbc/tests/bug69975.phpt [new file with mode: 0644]

index ddfbc4edbe5c624258beab9730c8d5782b5bb398..80af492638640595c6e71e2f679bf2b2bd48adfb 100644 (file)
@@ -1008,6 +1008,13 @@ int odbc_bindcols(odbc_result *result TSRMLS_DC)
                                                                NULL, 0, NULL, &displaysize);
                                }
 #endif
+                               /* Workaround for drivers that report NVARCHAR(MAX) columns as SQL_WVARCHAR with size 0 (bug #69975) */
+                               if (result->values[i].coltype == SQL_WVARCHAR && displaysize == 0) {
+                                       result->values[i].coltype = SQL_WLONGVARCHAR;
+                                       result->values[i].value = NULL;
+                                       break;
+                               }
+
                                /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
                                if (result->values[i].coltype == SQL_TIMESTAMP) {
                                        displaysize += 3;
diff --git a/ext/odbc/tests/bug69975.phpt b/ext/odbc/tests/bug69975.phpt
new file mode 100644 (file)
index 0000000..eca7564
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #69975 (PHP segfaults when accessing nvarchar(max) defined columns)
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+@odbc_exec($conn, 'CREATE DATABASE odbcTEST');
+odbc_exec($conn, 'CREATE TABLE FOO (ID INT, VARCHAR_COL NVARCHAR(MAX))');
+odbc_exec($conn, "INSERT INTO FOO VALUES (1, 'foo')");
+
+$result = odbc_exec($conn, "SELECT VARCHAR_COL FROM FOO");
+var_dump(odbc_fetch_array($result));
+
+echo "ready";
+?>
+--EXPECT--
+array(1) {
+  ["VARCHAR_COL"]=>
+  string(3) "foo"
+}
+ready
+--CLEAN--
+<?php
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+odbc_exec($conn, 'DROP TABLE FOO');
+odbc_exec($conn, 'DROP DATABASE odbcTEST');
+?>