|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
  [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
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits             | |||||||||||||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Fri Oct 31 03:00:01 2025 UTC | 
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 ()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:1196I 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.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).