Skip to content

php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs #193

Closed
wants to merge 5 commits into from

6 participants

@brandonkirsch

Fix for https://bugs.php.net/bug.php?id=61387

Changed conditional @ php_odbc.c:1774 to include the check:

     && Z_TYPE_P(tmp) != IS_NULL

This prevents a potential segfault on 1775 when zend_hash_update is called with Z_STR*(tmp) args.

Example script ("fetch_array.php"):

<?php
$c = odbc_connect('Driver=SQL Server Native Client 11.0;server=xxx;uid=xxx;pwd=xxx;Database=xxx','','');
$e = odbc_exec($c, 'SELECT NULL'); // The result set contains an unamed column with a NULL value
$row = odbc_fetch_array($e); // segfault when retrieved
?>

Backtrace:

Program received signal SIGSEGV, Segmentation fault.
zend_inline_hash_func (nKeyLength=, arKey=0x0) at /usr/src/php_fix/php-src/Zend/zend_hash.h:283
283 case 1: hash = ((hash << 5) + hash) + *arKey++; break;

#0 zend_inline_hash_func (nKeyLength=, arKey=0x0) at /usr/src/php_fix/php-src/Zend/zend_hash.h:283
#1 _zend_hash_add_or_update (ht=0xfce7d0, arKey=0x0, nKeyLength=1, pData=0x7fffffffab80, nDataSize=8, pDest=0x0, flag=1) at /usr/src/php_fix/php-src/Zend/zend_hash.c:218
#2 0x00000000005752af in php_odbc_fetch_hash (ht=, return_value=0xfcd038, result_type=2, return_value_ptr=, this_ptr=,
return_value_used=) at /usr/src/php_fix/php-src/ext/odbc/php_odbc.c:1775

BRANDON KIRSCH added some commits Sep 12, 2012
BRANDON KIRSCH php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs
php_odbc.c:1774 Changed the conditional to include the check:

	 && Z_TYPE_P(tmp) != IS_NULL

This prevents a potential segfault on 1775 where zend_hash_update is
called with Z_STR*(tmp) args.

Fixes Bug https://bugs.php.net/bug.php?id=61387
d0d978b
BRANDON KIRSCH Merge branch 'PHP-5.3' into PHP-5.4
* PHP-5.3:
  php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs
1a72814
BRANDON KIRSCH Merge branch 'PHP-5.4'
* PHP-5.4:
  php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs
1f11dde
@brandonkirsch

Fix for https://bugs.php.net/bug.php?id=61387

php_odbc_fetch_hash() / odbc_fetch_array()

Some ODBC Drivers (SQL Server Native Client) cause a segfault when using odbc_fetch_array() with certain result sets containing NULLs.

Example script ("fetch_array.php"):

<?php
$c = odbc_connect('Driver=SQL Server Native Client 11.0;server=xxx;uid=xxx;pwd=xxx;Database=xxx','','');
$e = odbc_exec($c, 'SELECT NULL'); // The result set contains an unamed column with a NULL value
$row = odbc_fetch_array($e); // segfault when retrieved
?>

Backtrace:

Program received signal SIGSEGV, Segmentation fault.
zend_inline_hash_func (nKeyLength=, arKey=0x0) at /usr/src/php_fix/php-src/Zend/zend_hash.h:283
283 case 1: hash = ((hash << 5) + hash) + *arKey++; break;

#0 zend_inline_hash_func (nKeyLength=, arKey=0x0) at /usr/src/php_fix/php-src/Zend/zend_hash.h:283
#1 _zend_hash_add_or_update (ht=0xfce7d0, arKey=0x0, nKeyLength=1, pData=0x7fffffffab80, nDataSize=8, pDest=0x0, flag=1) at /usr/src/php_fix/php-src/Zend/zend_hash.c:218
#2 0x00000000005752af in php_odbc_fetch_hash (ht=, return_value=0xfcd038, result_type=2, return_value_ptr=, this_ptr=,
return_value_used=) at /usr/src/php_fix/php-src/ext/odbc/php_odbc.c:1775

@ircmaxell

Looks good to me. The only thing I'd suggest is targeting the PR against 5.3, so that it can be merged up easier.

Other than that, the fix seems good (fixes a logic error where the type of the zval isn't the same)...

@LawnGnome LawnGnome and 1 other commented on an outdated diff Sep 13, 2012
ext/odbc/php_odbc.c
@@ -1765,7 +1765,7 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
if (result_type & ODBC_NUM) {
zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp, sizeof(zval *), NULL);
} else {
- if (!*(result->values[i].name)) {
+ if (!*(result->values[i].name) && Z_TYPE_P(tmp) != IS_NULL) {
@LawnGnome
LawnGnome added a note Sep 13, 2012

Should this be Z_TYPE_P(tmp) == IS_STRING, rather than not IS_NULL? From context, it's obvious that the only two possible zval types for tmp are IS_STRING and IS_NULL, but this strikes me as a potential gotcha if the function is changed down the track to return more native PHP types for numeric values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
BRANDON KIRSCH added some commits Sep 12, 2012
BRANDON KIRSCH php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs
php_odbc.c:1774 Changed the conditional to include the check:

	 && Z_TYPE_P(tmp) == IS_STRING

This avoids a potential segfault on 1775 where ZSTR_ macros are used
when the ZVAL is sometimes NULL.
383fcb3
BRANDON KIRSCH Merge branch 'PHP-5.3'
* PHP-5.3:
  php_odbc_fetch_hash() Fixed a segfault when fetching certain SQL NULLs
1f55a42
@brandonkirsch

Original patch used != IS_NULL. Per suggestion, changed to == IS_STRING.

@dsp
php.net member
dsp commented Sep 17, 2012

Please don't submit merges. Pull requests should only contain the actual changes. The PR should be for the lowest branch to which the changes apply (PHP-5.3 in this case).

So if you don't squash d0d978b and 383fcb3 together and don't include the merges (we will do the merging for you :)).

Anyway, thanks a lot for the patches. At a first glance they look okay and I am looking into merging them.

@brandonkirsch
@felipensp

I've pushed your changes manually, thanks!

@php-pulls

Comment on behalf of felipe at php.net:

Done.

@php-pulls php-pulls closed this Jun 24, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.