php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #59405 Segmentation fault on null values on ibm db2
Submitted: 2010-09-08 09:46 UTC Modified: 2010-09-16 09:04 UTC
Votes:14
Avg. Score:4.6 ± 1.0
Reproduced:14 of 14 (100.0%)
Same Version:2 (14.3%)
Same OS:4 (28.6%)
From: tuomaksen dot spammiposti at gmail dot com Assigned:
Status: Open Package: PDO_ODBC (PECL)
PHP Version: 5.3.2 OS: Linux (Ubuntu 10.04.1)
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2010-09-08 09:46 UTC] tuomaksen dot spammiposti at gmail dot com
Description:
------------
I'm trying to use a remote IBM DB2 database with IBM iSeriesAccess ODBC driver (version 6.1.0-1.2) from a Linux server. I noticed that php segfaults when it fetches a row that contains a null value.

I have tested the query shown in the code with unixODBC isql-tool (using iSeriesAccess driver) and with php's ibm_db2 -functions (using commercial DB2 Connect), the query works perfectly in these apps. Segmentation fault only appears using PDO_ODBC.

Also noticed that this query works ok in PDO_ODBC when using MS-SQL database.

Reproduce code:
---------------
#!/usr/bin/php
<?php
$db = new PDO('odbc:db2','db2inst1','db2pwd');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT 
		STTYNO AS ID,
		CASE WHEN STRAPV > 0 
		THEN 
			STRAPV
		ELSE 
			NULL 
		END AS NUM 
	FROM S36DB.PROJECTS";
$result = $db->query($sql);
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
	var_dump($row);
}

Expected result:
----------------
Output:
array(2) {
  ["ID"]=>
  string(2) "57"
  ["NUM"]=>
  string(5) "10102"
}
array(2) {
  ["ID"]=>
  string(2) "60"
  ["NUM"]=>
  string(5) "10102"
}
array(2) {
  ["ID"]=>
  string(2) "61"
  ["NUM"]=>
  string(5) "10102"
}
array(2) {
  ["ID"]=>
  string(2) "63"
  ["NUM"]=>
  NULL
}
array(2) {
  ["ID"]=>
  string(2) "65"
  ["NUM"]=>
  string(5) "10102"
}

Actual result:
--------------
Output:
array(2) {
  ["ID"]=>
  string(2) "57"
  ["NUM"]=>
  string(5) "10102"
}
array(2) {
  ["ID"]=>
  string(2) "60"
  ["NUM"]=>
  string(5) "10102"
}
array(2) {
  ["ID"]=>
  string(2) "61"
  ["NUM"]=>
  string(5) "10102"
}
Segmentation fault

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-09-16 07:39 UTC] tuomaksen dot spammiposti at gmail dot com
Ran the test script in gdb:

$ gdb /usr/bin/php
(gdb) run test.php
<removed some result rows>
array(2) {
  ["ID"]=>
  string(2) "61"
  ["NUM"]=>
  string(5) "10102"
}

Program received signal SIGSEGV, Segmentation fault.
memcpy () at ../sysdeps/x86_64/memcpy.S:513
513     ../sysdeps/x86_64/memcpy.S: No such file or directory.
        in ../sysdeps/x86_64/memcpy.S
(gdb) bt
#0  memcpy () at ../sysdeps/x86_64/memcpy.S:513
#1  0x0000000000678788 in _estrndup ()
#2  0x00007fffe75cbce0 in ?? () from /usr/lib/php5/20090626/pdo.so
#3  0x00007fffe75cec83 in ?? () from /usr/lib/php5/20090626/pdo.so
#4  0x00007fffe75cff0b in ?? () from /usr/lib/php5/20090626/pdo.so
#5  0x00007ffff427ef2a in xdebug_execute_internal (current_execute_data=0x7ffff7e78068, return_value_used=1)
    at /build/buildd/xdebug-2.0.5/build-php5/xdebug.c:1631
#6  0x00000000006e5f36 in ?? ()
#7  0x00000000006bd400 in execute ()
#8  0x00007ffff427eb9e in xdebug_execute (op_array=0x10a4b90) at /build/buildd/xdebug-2.0.5/build-php5/xdebug.c:1562
#9  0x000000000069512d in zend_execute_scripts ()
#10 0x0000000000640d98 in php_execute_script ()
#11 0x0000000000726236 in ?? ()
#12 0x00007ffff52a6c4d in __libc_start_main (main=<value optimized out>, argc=<value optimized out>, ubp_av=<value optimized out>, 
    init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>, stack_end=0x7fffffffe298) at libc-start.c:226
#13 0x000000000042c639 in _start ()
 [2010-09-16 09:04 UTC] tuomaksen dot spammiposti at gmail dot com
Here is the backtrace without xdebug and with php debug symbols:

(gdb) bt
#0  memcpy () at ../sysdeps/x86_64/memcpy.S:534
#1  0x0000000000678788 in _estrndup (s=0x10a1670 "", length=4294967295) at /usr/include/bits/string3.h:52
#2  0x00007fffe7808ce0 in fetch_value (stmt=0x10a1848, dest=0x10a2208, colno=18332912, type_override=0x1ffe4b1)
    at /build/buildd/php5-5.3.2/ext/pdo/pdo_stmt.c:635
#3  0x00007fffe780bc83 in T.275 (stmt=0x10a1848, return_value=0x0, how=PDO_FETCH_LAZY, ori=33547441, offset=1283556588, return_all=0x1f7e78068)
    at /build/buildd/php5-5.3.2/ext/pdo/pdo_stmt.c:1040
#4  0x00007fffe780cf0b in zim_PDOStatement_fetch (ht=17438940, return_value=0x10a28d8, return_value_ptr=0xfff3bfff, this_ptr=0x1ffe4b1, 
    return_value_used=1283556588) at /build/buildd/php5-5.3.2/ext/pdo/pdo_stmt.c:1316
#5  0x00000000006e611a in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7e78068) at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:313
#6  0x00000000006bd400 in execute (op_array=0x109e800) at /build/buildd/php5-5.3.2/Zend/zend_vm_execute.h:104
#7  0x000000000069512d in zend_execute_scripts (type=32767, retval=0x7fffffffbac0, file_count=3) at /build/buildd/php5-5.3.2/Zend/zend.c:1266
#8  0x0000000000640d98 in php_execute_script (primary_file=0x0) at /build/buildd/php5-5.3.2/main/main.c:2288
#9  0x0000000000726236 in main (argc=0, argv=0x1) at /build/buildd/php5-5.3.2/sapi/cli/php_cli.c:1196
 [2011-05-30 10:17 UTC] pratap_sms at yahoo dot com
Any plans to fix this.
 [2011-07-29 08:24 UTC] mail at tomsommer dot dk
A fix would be nice, yes.
 [2012-09-19 15:50 UTC] rufflesnet at gmail dot com
I have this problem on RHEL 6.1 with PHP 5.3.3 if it helps.
 [2012-10-19 12:26 UTC] tuomas dot angervuori at gmail dot com
This bug might be a 64bit issue only. At least so far I haven't managed to get 
segmentation fault on a 32bit server.

(Note also similar bugs #54007 and #46473)
 [2013-06-26 14:27 UTC] brandonkirsch at gmail dot com
I am very familiar with this problem - IT IS NOT A BUG IN PHP.

64-bit IBM iSeriesAccess ODBC drivers are built against an antiquated definition of what 64-bit ODBC should be. Instead, the IBM drivers use 32-bit values in places where 64-bits should be used.

The end result is that a 32-bit value ("-1" to represent NULL) is interpreted by 64-bit PHP as a large number, causing it to read an invalid memory address and therefore segfault.

You can ask IBM for a better ODBC driver, but they ignored us when we tried.

I have a custom patch for php_odbc.c that "fixes" the problem by hacking up PHP ODBC bindings to treat all ODBC SQL_NULL_DATA values as 32-bit. There are small potential downsides that can occur if you use this patch with a real 64-bit ODBC driver AND you try to access fields > 4GB.

http://www.perceptionilluminates.com/php/php_odbc.c -- It's antiquated (PHP 5.2.17) but it is also well commented, so you can port the hack to a modern version if you'd like.
 [2014-01-31 20:31 UTC] openam at gmail dot com
IBM has released a new Access Client Solutions Product, which appears to correct this problem. They have a post that discusses the improvements over iSeries Access for Linux (http://www.ibm.com/developerworks/ibmi/library/i-ibmi-access-client-solutions-linux/index.html).

You can visit the IBM i Access page at http://www-03.ibm.com/systems/power/software/i/access/solutions.html.
You don't need to install the entire ACS client just the Linux application package.

Here is a document on Obtaining Access Client Solutions (http://www-01.ibm.com/support/docview.wss?uid=nas8N1010355). The document does note that "at this time, you must be entitled to V6R1 or V7R1 IBM i OS." They did require a login and additional customer information.
 [2016-08-09 11:25 UTC] greenleaf123 at fastmail dot fm
I'm having same symptoms accessing a "local" db2 (Express-C) database on debian 8 (jessie) 64 bit:

php (PHP 5.6.20-0+deb8u1) crashes on null values.

Stack trace:
#0  __memcpy_sse2_unaligned ()
    at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:116
#1  0x00000000008553a8 in _estrndup (s=0x7ffff7fdf010 "data from line before", 
    length=4294967295, 
    __zend_filename=0x7ffff60f3c68 "/compile/php/php-src/ext/pdo/pdo_stmt.c", __zend_lineno=641, __zend_orig_filename=0x0, 
    __zend_orig_lineno=0)
    at /compile/php/php-src/Zend/zend_alloc.c:2655
#2  0x00007ffff60ea7bb in fetch_value (stmt=0x7ffff7fe2900, 
    dest=0x7fffec6f65b8, colno=2, type_override=0x0)
    at /compile/php/php-src/ext/pdo/pdo_stmt.c:641
#3  0x00007ffff60ebd49 in do_fetch (stmt=0x7ffff7fe2900, do_bind=1, 
    return_value=0x7ffff7fe2660, how=PDO_FETCH_BOTH, 
    ori=PDO_FETCH_ORI_NEXT, offset=0, return_all=0x0)
    at /compile/php/php-src/ext/pdo/pdo_stmt.c:1034
#4  0x00007ffff60ed6fb in zim_PDOStatement_fetchAll (ht=0, 
    return_value=0x7ffff7fe2810, return_value_ptr=0x7ffff7fa74a0, 
    this_ptr=0x7ffff7fe4a00, return_value_used=1)
    at /compile/php/php-src/ext/pdo/pdo_stmt.c:1519
#5  0x00000000008d3123 in zend_do_fcall_common_helper_SPEC (
    execute_data=0x7ffff7fa7b78)
    at /compile/php/php-src/Zend/zend_vm_execute.h:558


It may be a 32 bit vs 64 bit problem, yet as isql and even a self compiled (64 bit) odbc program work fine there seems to be a way to make it work (like SQLBindParameter vs. SQLGetData).

While the modified version http://www.perceptionilluminates.com/php/php_odbc.c may work around the issue (not tried), I'd suggest the issue to be addressed in odbc_stmt_get_col (ext/pdo_odbc/odbc_stmt.c).

odbc_stmt_get_col has accesses on data hidden in driver_data (I don't know enough on odbc programming to judge if these column accesses are "allowed" at all). One line is comparing "fetched_len == SQL_NULL_DATA" which indeed isn't working with the given values (fetched_len = 0xffffffff).
 [2016-08-09 16:40 UTC] greenleaf123 at fastmail dot fm
Ok, I have to correct myself: Neither isql nor my self compiled program work properly:
- isql is repeating previous data instead of "nullifing" the data correctly
- self compiled program only works because of initializing data properly - length of data returned by SQLGetData is indeed wrong.

For DB2 on z/OS I've found the following regarding the pointer to length of data in SQLGetData:
"For 64-bit applications, the data type SQLINTEGER, which was used in previous versions of DB2, is still valid. However, for maximum application portability, using SQLLEN is recommended."
Source: https://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/odbc/src/tpc/db2z_fngetdata.html

I haven't found that notice for DB2-LUW, though. Still it seems to work that way.

I suggest the following:
- When SQLGetData returns SQL_SUCCESS and the length returned is 0xffffffff (and larger as buffer size) it is to be interpreted as SQL_NULL_DATA.
- When SQLGetData returns SQL_SUCCESS_WITH_INFO and the length returned is 0xffffffff (and larger as buffer size) it is *not* to be mistaken as SQL_NULL_DATA.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Mon Apr 22 20:01:25 2019 UTC