From: Operating system: Linux (Ubuntu) PHP version: 5.3SVN-2010-12-10 (snap) Package: PostgreSQL related Bug Type: Bug Bug description:segfault in pgsql_stmt_execute() when postgres is down
Description: ------------ I've happened to encounter a segfault when I'm using persistent PostgreSQL connections in PHP 5.3.2. I haven't had the time (and won't have in the upcoming couple of weeks, sorry) to play around with it to generate a narrowed-down example, but for me, it's happened in the following scenario: 1) PHP running in a Lighttpd + FastCGI setup 2) database connection is made with a PDO pgsql connection to the local host with PDO::ATTR_PERSISTENT set to true 3) use the database connection sucessfully 4) turn off the database server 5) try to use the database connection again After this, instead of getting a "Connection failure"-style PDOException, PHP segfaults. (see backtrace below) After a small investigation, it turned out to happen because of the lack of an error check in pgsql_statement.c. Specifically: We're getting a segfault here, at line 187: 179 »···»···»···»···default: { 180 »···»···»···»···»···char *sqlstate = pdo_pgsql_sqlstate(S->result); 181 »···»···»···»···»···/* 42P05 means that the prepared statement already existed. this can happen if you use· 182 »···»···»···»···»··· * a connection pooling software line pgpool which doesn't close the db-connection once· 183 »···»···»···»···»··· * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no· 184 »···»···»···»···»··· * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we· 185 »···»···»···»···»··· * deallocate it and retry ONCE (thies 2005.12.15) 186 »···»···»···»···»··· */ 187 »···»···»···»···»···if (!strcmp(sqlstate, "42P05")) { Where pdo_pgsql_sqlstate() is: 92 #define pdo_pgsql_sqlstate(r) PQresultErrorField(r, PG_DIAG_SQLSTATE) Which, based on its documentation, can indeed return a NULL: PQresultErrorField Returns an individual field of an error report. char *PQresultErrorField(const PGresult *res, int fieldcode); fieldcode is an error field identifier; see the symbols listed below. NULL is returned if the PGresult is not an error or warning result, or does not include the specified field. The attached patch fixed this problem for me. It trivially won't break the !strcmp... code path, and on the other branch of the "if" statement also won't fail as sqlstate is passed over to pdo_pgsql_error_stmt(), which handles it being NULL properly. I've seen it happen with 5.3.2, but after peeking into the php-trunk source snapshots, it seems like this bug is still there. Expected result: ---------------- A PDOException telling us that the database connection has failed. Actual result: -------------- PHP segfaults with the following backtrace: #0 0x00007f7d06a655d9 in pgsql_stmt_execute (stmt=0x230ac08) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/ext/pdo_pgsql/pgsql_statement.c:187 sqlstate = 0x0 S = 0x2349878 H = 0x1f10030 status = PGRES_FATAL_ERROR #1 0x00007f7d06c7051a in zim_PDO_query (ht=1, return_value=0x2349530, return_value_ptr=0x230ac9c, this_ptr=0x22fc400, return_value_used=1) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/ext/pdo/pdo_dbh.c:1109 stmt = 0x230ac08 statement = 0x1dd6920 "00000" statement_len = 0 #2 0x00000000006e594a in zend_do_fcall_common_helper_SPEC (execute_data=0x1e176d0) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/Zend/zend_vm_execute.h:313 opline = 0x21416a8 should_change_scope = 184 '\270' #3 0x00000000006bcc30 in execute (op_array=0x1598470) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/Zend/zend_vm_execute.h:104 ret = 0 execute_data = 0x1e176d0 nested = 0 '\000' original_in_execution = 0 '\000' #4 0x000000000069495d in zend_execute_scripts (type=0, retval=0x7fffe11a3440, file_count=3) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/Zend/zend.c:1266 files = 0x7fffe11a3418 i = 1 file_handle = 0x7fffe11a5a40 orig_op_array = 0x0 orig_retval_ptr_ptr = 0xd8fd30 #5 0x0000000000640608 in php_execute_script (primary_file=0x0) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/main/main.c:2288 __orig_bailout = 0x400000001 __bailout = {{__jmpbuf = {0, 0, 0, 0, 32337904, 0, 181912586, 32637}, __mask_was_saved = 32, __saved_mask = {__val = {31439440, 0, 0, 0, 4294967295, 0, 0, 0, 181913152, 32637, 3776586748, 32767, 0, 0, 5, 0}}}} prepend_file_p = 0x0 append_file_p = 0x0 prepend_file = {type = 11236857, filename = 0x7f7d0aceee40 "", opened_path = 0x22fe5d4 ")))]", handle = {fd = 72, fp = 0x48, stream = {handle = 0x48, isatty = 1, mmap = {len = 31424656, pos = 0, map = 0x7f7d0a9ec58e, buf = 0x7fffe11a2b40 "\310+\032\341\377\177", old_handle = 0x36034da734074900, old_closer = 0x5}, reader = 0x1dfba50, fsizer = 0, closer = 0x1dfba50}}, free_filename = 212 '\324'} append_file = {type = 31439440, filename = 0x0, opened_path = 0xffffffff <Address 0xffffffff out of bounds>, handle = {fd = 181914002, fp = 0x7f7d0ad7c992, stream = {handle = 0x7f7d0ad7c992, isatty = -518380544, mmap = {len = 181902120, pos = 3776586804, map = 0x7f7d0acee0e0, buf = 0x7fffe11a2ac0 "(,\032\341\377\177", old_handle = 0x1dfba50, old_closer = 0}, reader = 0x5, fsizer = 0, closer = 0x7f7d0ad7cb30}}, free_filename = 0 '\000'} retval = 0 #6 0x00000000007224f4 in main (argc=32767, argv=0x0) at /usr/src/php5/php5-5.3.2-1ubuntu4.2.zorpos40.1/sapi/cgi/cgi_main.c:2110 __bailout = {{__jmpbuf = {0, 0, 0, 0, 2158641176, 3795055810, 14222272, 0}, __mask_was_saved = -1536278504, __saved_mask = {__val = {0 <repeats 16 times>}}}} free_query_string = 16777216 exit_status = 0 cgi = 0 c = 0 i = 14218272 len = 14218272 file_handle = {type = 165214479, filename = 0x4 <Address 0x4 out of bounds>, opened_path = 0x1335488 "/opt/scb/html/index.php", handle = {fd = 0, fp = 0x0, stream = {handle = 0x0, isatty = 20260736, mmap = {len = 0, pos = 3953, map = 0x0, buf = 0x7f7d0d266000 <Address 0x7f7d0d266000 out of bounds>, old_handle = 0x7f7d0d266000, old_closer = 0x13dea10}, reader = 0x6aa480 <zend_stream_stdio_closer>, fsizer = 0x6aaac0 <zend_stream_stdio_reader>, closer = 0x6aa540 <zend_stream_stdio_fsizer>}}, free_filename = 64 '@'} s = 0x1334428 "/opt/scb/html/index.php" behavior = 0 no_headers = 0 orig_optind = 0 orig_optarg = 0x0 script_file = 0x100000000 <Address 0x100000000 out of bounds> max_requests = 1 requests = 0 fastcgi = 1 bindpath = 0x100000001 <Address 0x100000001 out of bounds> fcgi_fd = 14218272 request = {listen_socket = 0, fd = 11, id = 0, keep = 3, closed = 1, in_len = 0, in_pad = 0, out_hdr = 0x0, out_pos = 0x0, out_buf = " [\032\341\377\177\000\000\001\006\000\001\bX\000\000\\r\\n <\\/div>\\r\\n \\r\\n <div id=\\\"sm_disk_usage_tooltip\\\" style=\\\"display: none\\\" class=\\\"tooltipWindow systemMonitorTooltip\\\">\\r\\n <span class=\\\"systemMonitorTooltip\\\">\\r\\"..., reserved = "<\\/span>\000\000\000\000\000\000\000", env = 0x0} repeats = 0 benchmark = 0 start = {tv_sec = 0, tv_usec = 0} end = {tv_sec = 0, tv_usec = 0} -- Edit bug report at http://bugs.php.net/bug.php?id=53517&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=53517&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=53517&r=trysnapshot53 Try a snapshot (trunk): http://bugs.php.net/fix.php?id=53517&r=trysnapshottrunk Fixed in SVN: http://bugs.php.net/fix.php?id=53517&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=53517&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=53517&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=53517&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=53517&r=needscript Try newer version: http://bugs.php.net/fix.php?id=53517&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=53517&r=support Expected behavior: http://bugs.php.net/fix.php?id=53517&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=53517&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=53517&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=53517&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=53517&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=53517&r=dst IIS Stability: http://bugs.php.net/fix.php?id=53517&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=53517&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=53517&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=53517&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=53517&r=mysqlcfg