Edit report at http://bugs.php.net/bug.php?id=53517&edit=1

 ID:                 53517
 Updated by:         fel...@php.net
 Reported by:        gyp at balabit dot hu
 Summary:            segfault in pgsql_stmt_execute() when postgres is
                     down
-Status:             Open
+Status:             Closed
 Type:               Bug
 Package:            PostgreSQL related
 Operating System:   Linux (Ubuntu)
 PHP Version:        5.3SVN-2010-12-10 (snap)
-Assigned To:        
+Assigned To:        felipe
 Block user comment: N
 Private report:     N

 New Comment:

This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Thanks for the patch!


Previous Comments:
------------------------------------------------------------------------
[2010-12-10 13:26:12] gyp at balabit dot hu

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 this bug report at http://bugs.php.net/bug.php?id=53517&edit=1

Reply via email to