php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #61387 NULL valued anonymous column causes segfault in odbc_fetch_array
Submitted: 2012-03-14 15:19 UTC Modified: 2013-04-09 02:57 UTC
Votes:4
Avg. Score:4.5 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: marec at stringdata dot cz Assigned: ssb (profile)
Status: Closed Package: ODBC related
PHP Version: 5.3.10 OS: windows server 2003 R2
Private report: No CVE-ID: None
 [2012-03-14 15:19 UTC] marec at stringdata dot cz
Description:
------------
odbc_fetch_array segfaults when the result consists of one-column anonymous NULL-valued tuple

our environment:
OS: windows server 2003 R2, apache 2.2 + mod_fcgid + PHP5.3.10 (reproducible with 5.3.6)
DB: SQL Server 2005
odbc driver: SQL Server Native Client 10.0

tried also with postgres, it seems to me that postgres amends the result with generated name of that column ('sum' in this case)

Test script:
---------------
$conn = odbc_connect(
  "Driver={SQL Server Native Client 10.0};Server=<some microsoft sql server>;Database=<any db name>;Trusted_Connection=yes"
, ''
, ''
);

$res = odbc_exec(
  $conn
, 'SELECT SUM(1)
  FROM information_schema.tables
  WHERE 3 = 2'
);

$row = odbc_fetch_array($res);
odbc_free_result($res);
odbc_close($conn);
var_dump($row);

Expected result:
----------------
array(1) {[0]=> NULL}

or E_WARNING

Actual result:
--------------
segfault, apache log says:

[warn] [client x.x.x.x] (OS 109)The pipe has been ended.  : mod_fcgid: get overlap result error
[error] [client x.x.x.x] Premature end of script headers: foo.php
[info] mod_fcgid: process C:/Webserver/Apache2.2/php-5.3.10/php-cgi.exe(4420) exit(communication error), return code -1073741819

eventlog says:
Faulting application php-cgi.exe, version 5.3.10.0, faulting module php5.dll, version 5.3.10.0, fault address 0x000858df.

PHP itself does not produce any sort of output

Patches

php_odbc_fetch_hash--segfault-fix (last revision 2012-09-13 15:04 UTC by brandonkirsch at gmail dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-09-12 21:56 UTC] brandonkirsch at gmail dot com
I've been fighting with this bug all day long on PHP 5.2.17 *AND* PHP 5.3.16 for 
64-bit Linux.

I have isolated the problem to odbc_fetch_array() for result sets that contain 
an anonymous (unnamed) column with a NULL value. If NULL value is aliased 
("SELECT NULL as SOMETHING") there is no crash.  If an anonymous (unnamed) 
column contains anything other than NULL, there is no crash.

Test Script:

$sql = 'SELECT NULL';

$c = odbc_connect('Driver=SQL Server Native Client 
11.0;server=hpesc1;uid=xxx;pwd=xxx;Database=xxx','','');

$e = odbc_exec($c, $sql);

$row = odbc_fetch_array($e);


Here are different combinations of SQL that will or won't crash PHP:

$sql = 'SELECT NULL'; // PHP SEGFAULT
$sql = 'SELECT NULL as [one]'; // OK
$sql = 'SELECT 1'; // OK
$sql = 'SELECT 1, NULL'; // SEGFAULT
$sql = 'SELECT 1, NULL as [two]'; // OK

And a backtrace:


#0  zend_inline_hash_func (nKeyLength=<optimized out>, arKey=0x0) at 
/usr/src/php-5.3.16/Zend/zend_hash.h:283
#1  _zend_hash_add_or_update (ht=0xfce8b8, arKey=0x0, nKeyLength=1, 
pData=0x7fffffffab90, nDataSize=8, pDest=0x0, flag=1) at /usr/src/php-
5.3.16/Zend/zend_hash.c:218
#2  0x000000000057528f in php_odbc_fetch_hash (ht=<optimized out>, 
return_value=0xfccfe8, result_type=2, return_value_ptr=<optimized out>, 
this_ptr=<optimized out>, 
    return_value_used=<optimized out>) at /usr/src/php-
5.3.16/ext/odbc/php_odbc.c:1775


My comprehension of C & the PHP source code is very limited, but it looks like 
php_odbc.c lines 1752 (handling of SQL_NULL_DATA) and 1771 through 1779 are 
suspect.  I think php_odbc.c may be using zend_hash_update improperly but I 
can't tell for sure.

And finally, here is a workaround script that DOES NOT segfault:


<?php


$c = odbc_connect('Driver=SQL Server Native Client 
11.0;server=hpesc1;uid=xxx;pwd=xxx;Database=xxx','','');

$e = odbc_exec($c, 'SELECT NULL');

$true = odbc_fetch_row($e);

$row = odbc_result($e, 1);

var_dump($row); // "NULL" -- no segfault
 [2012-09-12 23:51 UTC] brandonkirsch at gmail dot com
This problem is isolated to the SQL Server Native Client ODBC Driver. Most other 
ODBC drivers will automatically provide some type of aliased column name for 
arbitrary values that you select.

When using a SELECT 'VALUE' statement with SQL Server ODBC, the 
php_odbc_fetch_hash() function returns the column as 'VALUE' => 'VALUE' -- that 
is, the value you select is also the key in the array.

The problem occurs at the end of the php_odbc_fetch_hash() function in 
php_odbc.c (for me, on 5.2.17 it begins on line 1510) and it looks like this:

if (!*(result->values[i].name)) { // GDB says this evaluates to 1
  zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(tmp),
    Z_STRLEN_P(tmp)+1, &tmp, sizeof(zval *), NULL); // SEGFAULT

This usage of zend_hash_update() causes a segfault in PHP 5.2.17 and PHP 5.3.16.  
I guess that result->values[i].name looks legit and/or usable when it is not.

I updated the if statement to read:

if (!*(result->values[i].name) && Z_TYPE_P(tmp) != IS_NULL) { // Evaluates false 
for SQL NULLs that sets ZVAL_NULL(tmp)

This skips the incorrect usage of zend_hash_update with Z_STR* functions and 
proceeds to the "else" condition that handles it correctly.

For us, this solution works perfectly and the end-result is array("" => NULL) 
instead of a segfault.  Other unaliased NULL values from other databases 
continue to work the same way as before (iSeries ODBC drivers return 
array("0001" => NULL))

Here's the rub:  I have no idea how to generate or submit a patch.  But this fix 
works.  If someone can turn this into a real fix and run with it, great.  If 
someone would contact me and help me turn it into a real patch, I would be happy 
to help.
 [2013-04-09 02:57 UTC] laruence@php.net
-Assigned To: +Assigned To: ssb
 [2013-04-09 02:57 UTC] laruence@php.net
ssb, are you still active for odbc bugs fix?
 [2013-04-15 13:50 UTC] brandonkirsch at gmail dot com
Here's a fix for this issue: https://github.com/php/php-src/pull/193

Please accept it! Would be nice to have a fix before the next 5.5 beta.
 [2013-06-24 17:49 UTC] felipe@php.net
Automatic comment on behalf of felipensp@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=8776555d7a4fa510e79a986799921b4248c628c0
Log: - Fixed bug #61387 (NULL valued anonymous column causes segfault in odbc_fetch_array) patch by: Brandon Kirsch
 [2013-06-24 17:49 UTC] felipe@php.net
-Status: Assigned +Status: Closed
 [2014-10-07 23:18 UTC] stas@php.net
Automatic comment on behalf of felipensp@gmail.com
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=8776555d7a4fa510e79a986799921b4248c628c0
Log: - Fixed bug #61387 (NULL valued anonymous column causes segfault in odbc_fetch_array) patch by: Brandon Kirsch
 [2014-10-07 23:29 UTC] stas@php.net
Automatic comment on behalf of felipensp@gmail.com
Revision: http://git.php.net/?p=php-src-security.git;a=commit;h=8776555d7a4fa510e79a986799921b4248c628c0
Log: - Fixed bug #61387 (NULL valued anonymous column causes segfault in odbc_fetch_array) patch by: Brandon Kirsch
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 10:01:29 2024 UTC