php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69975 PHP segfaults when accessing nvarchar(max) defined columns
Submitted: 2015-07-01 08:38 UTC Modified: 2016-07-05 09:12 UTC
From: jgeert1 at its dot jnj dot com Assigned: cmb
Status: Closed Package: ODBC related
PHP Version: 5.5.26 OS: Windows Server 2012R2
Private report: No CVE-ID: 2015-8879
 [2015-07-01 08:38 UTC] jgeert1 at its dot jnj dot com
Description:
------------
if you have a MS SQL Database with a table that contains columns defined as NVARCHAR(MAX), PHP will crash Apache when executing the odbc_fetch_array function.

Error noted in the Windows Event viewer:

Faulting application name: httpd.exe, version: 2.4.9.0, time stamp: 0x53258cd5
Faulting module name: MSVCR110.dll, version: 11.0.51106.1, time stamp: 0x5098826e
Exception code: 0xc0000005
Fault offset: 0x000000000003c664
Faulting process id: 0x5c4
Faulting application start time: 0x01d0b31ba3eb507f
Faulting application path: D:\wamp\bin\apache\apache2.4.9\bin\httpd.exe
Faulting module path: C:\windows\system32\MSVCR110.dll
Report Id: 2d47d2ee-1f12-11e5-943b-005056915a28

Additional info:
The ODBC driver sees the NVARCHAR(MAX) column as a NVARCHAR(0) column. Probably the zero is causing the odbc driver to loop and consume all available memory.

As a workaround I've changed the DSN to use "SQL Server" instead of "SQL Server Native Client 10.0". This is an "old" driver (version 6) which does not support MARS but at least does not cause Apache to crash. It sees the NVARCHAR(MAX) columns as NTEXT columns with a maximum (maxint)size.




Test script:
---------------
$dbs = odbc_connect("Driver={SQL Server Native Client 10.0"}";Server=MYSERVER1;Database=MYDBS;MARS_Connection=Yes;,"username","password",SQL_CUR_USE_ODBC);
$result = odbc_exec($dbs, "select * from Table1");
// Table1 should have a column defined as "NVARCHAR(MAX)"

$row = odbc_fetch_array($result);

// Apache is crashing when executing the odbc_fetch_array

Expected result:
----------------
Please provide support for NVARCHAR(MAX) columns in all odbc implementations for PHP. I did the test with all recent versions of PHP (except version 7) but all of them crash when accessing this type of column though odbc.

I know this has been reported many times before, but it has never been finally resolved by putting the support into the binaries for all versions of php.

Actual result:
--------------
Crash of Apache.

Patches

odbc-wvarchar-native-draft (last revision 2015-07-02 14:17 UTC) by cmb@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-01 14:41 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2015-07-01 14:41 UTC] ab@php.net
Thanks for the report. 

What you say is not quite correct, a lot of ext/odbc related bugs was fixed in the last PHP5 releases, please check the changelog.

Could you please also check #68964? As I didn't have the final response there, while the patch was already in releases.

What ODBCVER does your phpinfo() show? Which is the SqlServer version?

You should probably know also, that nvarchar and others are long deprecated https://msdn.microsoft.com/en-us/library/ms187993%28v=sql.90%29.aspx so should not be used. We depend on the underlying library here, it's not about us making decisions supporting them or not. However it shouldn't crash, that's clear.

Thanks.
 [2015-07-01 14:42 UTC] ab@php.net
-Package: PDO ODBC +Package: ODBC related
 [2015-07-01 14:42 UTC] ab@php.net
fix category
 [2015-07-02 07:27 UTC] jgeert1 at its dot jnj dot com
-Status: Feedback +Status: Open
 [2015-07-02 07:27 UTC] jgeert1 at its dot jnj dot com
Thanks for your fast reply.
Don't get me wrong here, I'm really satisfied with the work that you guys are doing here. And I'm even impressed by the quality of it.

I just looked at #68964 and yes it's almost the same issue. I also had that same error in the beginning (memory exhausted), but when I changed the max memory limit in php.ini to 1024M, the error did not show up again, instead Apache started crashing as a result of it.

The database server (seperate system) is running SQL Server 11.0.5058 (SQL Server 2012). The ODBC driver I'm using is "SQL Server Native Client 11.0" (2011.110.2100.60).

The database is using some tables with columns defined as "nvarchar(max)", this type is not deprecated as you've mentioned, it's even recommended to use them ("ntext", "text" and "image" types are deprecated).

When I'm using the "SQL Server Native Client 11.0" odbc driver, I notice that the columns are reported (using the odbc_columns calls) as "nvarchar(0)". But when I'm using the "SQL Server" odbc server, these same columns are reported as "ntext" with a size of 2147483646 eventhough it's the same column in the database wich is indeed defined as "nvarchar(max)".

Anyway if there's anything I can (investigate,test,..), just let me know as I really would like this to be resolved.

Currenlty I'm using the 64-bit versions of Apache and PHP.

Thanks.
 [2015-07-02 11:12 UTC] cmb@php.net
> Anyway if there's anything I can (investigate,test,..), just let
> me know as I really would like this to be resolved.

It might be helpful if you can post an ODBC trace for the given
test script. If the trace is large, it might be best to put it on
<https://gist.github.com/> or someone else, but not directly in
this ticket. How to create an ODBC trace is described on
<https://support.microsoft.com/en-us/kb/274551>. And please make
sure there is no confidential information contained in the trace
(password etc.)
 [2015-07-02 12:05 UTC] jgeert1 at its dot jnj dot com
The odbc trace can be found here:
https://gist.githubusercontent.com/anonymous/761c084d36f586862f08/raw/SQLLOG
Thanks.
 [2015-07-02 13:01 UTC] jgeert1 at its dot jnj dot com
This is the testscript I've used:
     $db_datastage = odbc_connect($dsn,$user,$pwd,SQL_CUR_USE_ODBC);	
     $res = odbc_exec($db_datastage,"select top 10 * from SN.cmdb_ci");
     while ($row = odbc_fetch_array($res)) {
	var_dump($row);
     }
     odbc_close($db_datastage);

This trace is the failing one (using "SQL Server Native Client 11.0" as driver):
https://gist.githubusercontent.com/anonymous/757e0f1fabeefbbb1abb/raw/SQLLOG1

This trace is the successful one (using "SQL Server" as driver):
https://gist.githubusercontent.com/anonymous/6d59f9903ca76d43095d/raw/sqllog2

It looks like it's having an issue when fetching the result (2nd result) as it's displaying: 
DIAG [01004] [Microsoft][SQL Server Native Client 11.0]String data, right truncation (0) 

Looks like a small buffer problem somewhere?
 [2015-07-02 14:16 UTC] cmb@php.net
Thanks for the traces.

At a first glance the problem is that SQLColAttributes()
requesting SQL_COLUMN_DISPLAY_SIZE for column 5 yields 0 for the
Native Driver, but 1073741823 (0x3fffffff) for the SQL Server
driver, whereby the column type is reported as SQL_WVARCHAR (-9)
and SQL_WLONGVARCHAR (-10), respectively. This results in a buffer
of only 1 byte to be emalloc'd()[1], what's likely to cause
problems.

However, I'm confused, because SQL_WVARCHAR is supposed to request
SQL_DESC_OCTET_LENGTH instead of SQL_COLUMN_DISPLAY_SIZE[2]. Maybe
a driver mapping?

Maybe the attached patch "odbc-wvarchar-native-draft" points in
the right direction?

[1] <https://github.com/php/php-src/blob/PHP-5.5.26/ext/odbc/php_odbc.c#L1020>
[2] <https://github.com/php/php-src/blob/PHP-5.5.26/ext/odbc/php_odbc.c#L995>
 [2015-07-02 14:17 UTC] cmb@php.net
The following patch has been added/updated:

Patch Name: odbc-wvarchar-native-draft
Revision:   1435846631
URL:        https://bugs.php.net/patch-display.php?bug=69975&patch=odbc-wvarchar-native-draft&revision=1435846631
 [2015-07-02 14:24 UTC] jgeert1 at its dot jnj dot com
Wow that was fast :-)
What do I need to do to get a compiled version for Windows 64-bit?
Thanks.
 [2015-07-02 16:59 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: cmb
 [2015-07-02 16:59 UTC] cmb@php.net
I have now set up a testing environment with SQL Server 2014 and
can reproduce the issue. My patch was way too short-sighted (it
prevents the segfault, but does return empty strings). I'll have
to investigate further.
 [2015-07-02 20:03 UTC] cmb@php.net
-Summary: PHP is causing Apache to crash when accessing nvarchar(max) defined columns +Summary: PHP segfaults when accessing nvarchar(max) defined columns
 [2015-07-02 20:04 UTC] ab@php.net
-Summary: PHP segfaults when accessing nvarchar(max) defined columns +Summary: PHP is causing Apache to crash when accessing nvarchar(max) defined columns
 [2015-07-02 20:04 UTC] ab@php.net
@jgeert1, ahh, you're right. Still, it could be a driver mess.

@cmb, have you tried to raise the ODBCVER? See ext/odbc/config.w32, IMHO 3.5 could be done for master, if there's no other solution. Still many issues with 3.0 and older. But on the other hand, if you can fix it with 3.0, so be.

Thanks.
 [2015-07-02 20:06 UTC] cmb@php.net
-Summary: PHP is causing Apache to crash when accessing nvarchar(max) defined columns +Summary: PHP segfaults when accessing nvarchar(max) defined columns -Type: Feature/Change Request +Type: Bug
 [2015-07-02 21:04 UTC] cmb@php.net
I've tested with odbcver=0x0350 and 0x0351 and got segfaults, too.

Actually the problem is rather clear in the meantime. According to
MSDN[1] nvarchar(max) has a maximum size of 2GB. Even if the
driver would report this as displaylength, so much memory could
usually not be allocated. Apparently, nvarchar(max) has to be
treated the same as SQL_WLONGVARCHAR. The SQL Server driver does
this, but not the SQL Server Native Client 11.0 driver
(2011.110.3000.0). The fix appears to be a no-brainer (similar to
the attached draft patch, but additionally setting .coltype to
SQL_WLONGVARCHAR, and of course fixing the assignment in the if
condition).

I can confirm that #68964 is already fixed. An ntext column is
reported as SQL_WLONGVARCHAR by both drivers (ODBCVER 03x00 as
well as 0x351).

Interestingly, bug #67437 suggests that some drivers report a size
of ~ 2GB for nvarchar(max). I'll have a closer look on that.

[1] <https://msdn.microsoft.com/en-us/library/ms186939(v=sql.120).aspx>
 [2015-07-02 22:30 UTC] cmb@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=16db4d1462bf3eacb93c0cd940f799160a284b24
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 [2015-07-02 22:30 UTC] cmb@php.net
-Status: Verified +Status: Closed
 [2015-07-02 22:38 UTC] cmb@php.net
The fix for this bug has been committed for PHP 5.6 and master.

You can download the latest Windows snapshot from
<http://windows.php.net/snapshots/>. Note that it might take some
time for the next snapshot to be built.
 
Thank you for the report, and for helping us make PHP better.

I have not been able to reproduce #67437, and therefore didn't
cater to it; see also the commit message.
 [2015-07-03 11:35 UTC] cmb@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=344ff5dd4c538eaebea075f7705321f8b86d0b47
Log: fixed fix #69975 wrt. ODBCVER &lt; 0x0300
 [2015-07-07 23:36 UTC] ab@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=344ff5dd4c538eaebea075f7705321f8b86d0b47
Log: fixed fix #69975 wrt. ODBCVER &lt; 0x0300
 [2015-07-07 23:36 UTC] ab@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=16db4d1462bf3eacb93c0cd940f799160a284b24
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 [2016-07-05 09:12 UTC] kaplan@php.net
-CVE-ID: +CVE-ID: 2015-8879
 [2016-07-05 09:12 UTC] kaplan@php.net
Seems a CVE was assigned to this bug, although not everyone agrees to that, see https://bugzilla.redhat.com/show_bug.cgi?id=1338912
 [2016-07-08 13:36 UTC] jpauli@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=82637e818776d4fe778fb1dbac26eeece02e900c
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 [2016-07-14 19:20 UTC] ab@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=82637e818776d4fe778fb1dbac26eeece02e900c
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 [2016-07-14 19:22 UTC] ab@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=82637e818776d4fe778fb1dbac26eeece02e900c
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 [2016-10-17 10:11 UTC] bwoebi@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=php-src.git;a=commit;h=82637e818776d4fe778fb1dbac26eeece02e900c
Log: Fix #69975: PHP segfaults when accessing nvarchar(max) defined columns
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sat Feb 25 00:01:41 2017 UTC