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

Reply via email to