[ODBC] Segmentation fault of psqlodbcw.so during connect to postgresserver - Mailing list pgsql-odbc

From 12级控制(1)丁海强
Subject [ODBC] Segmentation fault of psqlodbcw.so during connect to postgresserver
Date
Msg-id 402ad1b7.4e2a.15e125c4533.Coremail.dinghaiqiang666@163.com
Whole thread Raw
List pgsql-odbc

hi

Because i send the email to your organization failed with company server, so i change the server and send the bug description again.

psql odbc expert, recently we met an occasional issue that psqlodbcw.so will be crashed during connect the postgres server.

psqlodbcw.so version: psqlodbc-09.05.0400

postgres server version: postgresql-9.6.2

 

Test step:

1 Start up postgres server

2 Launcher a process which call psqlodbc driver to connect and disconnect postgres server in sequential.

3 Fast shutdown the postgres server, however, the client process will crash occasionally.

 

 

Crash information:

 

Program terminated with signal SIGSEGV, Segmentation fault.

#0  strlen () at ../sysdeps/x86_64/strlen.S:106

106     in ../sysdeps/x86_64/strlen.S

(gdb) bt full

#0  strlen () at ../sysdeps/x86_64/strlen.S:106

No locals.

#1  0x00007f5ede5db7ce in __GI___strdup (s=0x0) at strdup.c:41 è if the parameter is null, the “strdup” will crashed

        len = <optimized out>

        new = <optimized out>

#2  0x00007f5ed40e0c0d in CC_connect (self=0x7f5eb0014740, salt_para=0x7f5ed8d4e3b0 "") at connection.c:1045

        ci = 0x7f5eb0014828

        func = 0x7f5ed413831f "CC_connect"

        ret = 1 '\001'

        saverr = 0x0

        retsend = 1 '\001'

#3  0x00007f5ed40f3cbd in PGAPI_DriverConnect (hdbc=0x7f5eb0014740, hwnd=0x0,

    szConnStrIn=0x7f5eb00026b0 "Driver=PostgreSQL;Server=192.168.1.3;Port=5433;Database=postgreswd;Uid=_nokfssystestpostgres;Pwd=", cbConnStrIn=-3,

0;Protocol=7.4;FakeOidIndex=0;ShowOidColumn=0;RowVersioning=0;ShowSystemTable"..., cbConnStrOutMax=2048, pcbConnStrOut=0x0, fDriverCompletion=1)

    at drvconn.c:221

        func = 0x7f5ed413a2c0 "PGAPI_DriverConnect"

        conn = 0x7f5eb0014740

        ci = 0x7f5eb0014828

        paramRequired = 0

        didUI = 0

        result = -11251

        connStrIn = 0x0

mes>, "\246\346\027\340^\177", '\000' <repeats 58 times>...

        retval = 0

        salt = "\000\000\000\000"

        len = 0

---Type <return> to continue, or q <return> to quit---

        lenStrout = -904

#4  0x00007f5ed4124984 in SQLDriverConnect (hdbc=0x7f5eb0014740, hwnd=0x0,

    szConnStrIn=0x7f5eb00026b0 "Driver=PostgreSQL;Server=192.168.1.3;Port=5433;Database=postgreswd;Uid=_nokfssystestpostgres;Pwd=", cbConnStrIn=-3,

0;Protocol=7.4;FakeOidIndex=0;ShowOidColumn=0;RowVersioning=0;ShowSystemTable"..., cbConnStrOutMax=2048, pcbConnStrOut=0x0, fDriverCompletion=1)

    at odbcapi.c:190

        ret = 0

        conn = 0x7f5eb0014740

#5  0x00007f5ee0141309 in SQLDriverConnect () from /usr/lib64/libodbc.so.2

……

 

The stack information of address (0x7f5eb0014740):

 

(gdb) p self

$1 = (ConnectionClass *) 0x7f5eb0014740

(gdb) p* self

$2 = {henv = 0x7f5eb0014700, login_timeout = 5, autocommit_public = 1 '\001', stmtOptions = {maxRows = 0, maxLength = 0, keyset_size = 0, cursor_type = 0,

    scroll_concurrency = 1, retrieve_data = 1, use_bookmarks = 0, bookmark_ptr = 0x0, metadata_id = 0, stmt_timeout = 0}, ardOptions = {

    size_of_rowset = 1, bind_size = 0, row_operation_ptr = 0x0, row_offset_ptr = 0x0, bookmark = 0x0, bindings = 0x0, allocated = 0,

    size_of_rowset_odbc2 = 1}, apdOptions = {paramset_size = 1, param_bind_type = 0, param_operation_ptr = 0x0, param_offset_ptr = 0x0, bookmark = 0x0,

    parameters = 0x0, allocated = 0, paramset_size_dummy = 1}, __error_message = 0x0, __error_number = 110, sqlstate = "\000\000\000\000\000\000\000",

  status = CONN_NOT_CONNECTED, connInfo = {dsn = '\000' <repeats 255 times>, desc = '\000' <repeats 255 times>,

    drivername = "PostgreSQL", '\000' <repeats 245 times>, server = "192.168.1.3", '\000' <repeats 244 times>,

    database = "postgreswd", '\000' <repeats 245 times>, username = "_nokfssystestpostgres", '\000' <repeats 234 times>, password = {name = 0x0},

    port = "5433\000\000\000\000\000", sslmode = "disable\000\000\000\000\000\000\000\000", onlyread = "0\000\000\000\000\000\000\000\000",

    fake_oid_index = "0\000\000\000\000\000\000\000\000", show_oid_column = "0\000\000\000\000\000\000\000\000",

    row_versioning = "0\000\000\000\000\000\000\000\000", show_system_tables = "0\000\000\000\000\000\000\000\000",

    translation_dll = '\000' <repeats 255 times>, translation_option = "\000\000\000\000\000\000\000\000\000", password_required = 0 '\000',

    conn_settings = {name = 0x0}, allow_keyset = 1 '\001', updatable_cursors = 0 '\000', lf_conversion = 0 '\000', true_is_minus1 = 0 '\000',

    int8_as = 0 '\000', bytea_as_longvarbinary = 0 '\000', use_server_side_prepare = 1 '\001', lower_case_identifier = 0 '\000',

    rollback_on_error = -1 '\377', force_abbrev_connstr = 0 '\000', bde_environment = 0 '\000', fake_mss = 0 '\000', cvt_null_date_string = 0 '\000',

    accessible_only = 0 '\000', ignore_round_trip_time = 0 '\000', disable_keepalive = 0 '\000', gssauth_use_gssapi = 0 '\000', extra_opts = 0,

    keepalive_idle = -1, keepalive_interval = -1, drivers = {drivername = {name = 0x7f5eb0014620 "PostgreSQL Unicode"}, fetch_max = 100,

      unknown_sizes = 0, max_varchar_size = 255, max_longvarchar_size = 8190, debug = 0 '\000', commlog = 0 '\000', unique_index = 1 '\001',

      onlyread = 0 '\000', use_declarefetch = 0 '\000', text_as_longvarchar = 1 '\001', unknowns_as_longvarchar = 0 '\000', bools_as_char = 1 '\001',

      lie = 0 '\000', parse = 0 '\000', extra_systable_prefixes = "dd_", '\000' <repeats 252 times>, protocol = "7.4\000\000\000\000\000\000",

      conn_settings = {name = 0x0}}}, stmts = 0x7f5eb0014590, num_stmts = 16, ncursors = 0, pqconn = 0x7f5eb0015800, lobj_type = -999, coli_allocated = 0,

  ntables = 0, col_info = 0x0, translation_option = 0, translation_handle = 0x0, DataSourceToDriver = 0x0, DriverToDataSource = 0x0,

  transact_status = 1 '\001', pg_version = "9.6.2", '\000' <repeats 122 times>, pg_version_major = 9, pg_version_minor = 6, ms_jet = 0 '\000',

  unicode = 0 '\000', result_uncommitted = 0 '\000', lo_is_domain = 0 '\000', original_client_encoding = 0x0, server_encoding = 0x0, ccsc = 0,

  mb_maxbyte_per_char = 1, isolation = 2, current_schema = 0x0, current_schema_valid = 0 '\000', unnamed_prepared_stmt = 0x0, max_identifier_length = -1,

  num_discardp = 0, discardp = 0x0, num_descs = 16, descs = 0x7f5eb0015280, schemaIns = {name = 0x0}, tableIns = {name = 0x0}, stmt_timeout_in_effect = 0,

  cs = {__data = {__lock = 1, __count = 1, __owner = 3492, __nusers = 1, __kind = 1, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}},

    __size = "\001\000\000\000\001\000\000\000\244\r\000\000\001\000\000\000\001", '\000' <repeats 22 times>, __align = 4294967297}, slock = {__data = {

      __lock = 0, __count = 0, __owner = 0, __nusers = 0, __kind = 1, __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}},

    __size = '\000' <repeats 16 times>, "\001", '\000' <repeats 22 times>, __align = 0}}

 

Crash reason:

 

Following is the part related psqlodbcw.so function “CC_connect”:

 

…… 

        ret = LIBPQ_CC_connect(self, salt_para);

        if (ret <= 0)

                return ret;

 

        CC_set_translation(self);

 

        /*

        * Send any initial settings

        */

 

        /*

        * Since these functions allocate statements, and since the connection

        * is not established yet, it would violate odbc state transition

        * rules.  Therefore, these functions call the corresponding local

        * function instead.

        */

 

        /* Global settings */

retsend = CC_send_settings(self, GET_NAME(self->connInfo.drivers.conn_settings));

        /* Per Datasource settings */

if (retsend)

        retsend = CC_send_settings(self, GET_NAME(self->connInfo.conn_settings));

 

        if (CC_get_errornumber(self) > 0)

                saverr = strdup(CC_get_errormsg(self));    è Dinghaiqiang: if the errormessage is null, it will cause crashed.

        CC_clear_error(self);                   /* clear any error */

        CC_lookup_lo(self);                     /* a hack to get the oid of

                                                   our large object oid type */

 

  ……

 

From the coredump information we know that the function “CC_connect” call “strdup” to copy the errormessage directly when the error number > 0. However the “strdup ” will crash when the parameter is null.

 

How to generate that error we have reproduced this issue and then found following scenarios will cause this crash.

 

gdb) where

#0  handle_pgres_error (self=0x647490, pgres=0x64d1a0, comment=0x7ffff1934321 "CC_send_query", res=0x64ca60, fatal=0) at connection.c:812

#1  0x00007ffff18dc7c2 in receive_libpq_notice (arg=0x7fffffff6ed0, pgres=0x64d1a0) at connection.c:917

#2  0x00007ffff7537650 in pqGetErrorNotice3 () from /opt/nokia/lib64/libpq.so.5

#3  0x00007ffff753779f in pqParseInput3 () from /opt/nokia/lib64/libpq.so.5

#4  0x00007ffff753131d in PQgetResult () from /opt/nokia/lib64/libpq.so.5

#5  0x00007ffff18defec in CC_send_query_append (self=0x647490, query=0x6609b0 "SET extra_float_digits = 2", qi=0x0, flag=0, stmt=0x64cd80, appendq=0x0) at connection.c:1715

#6  0x00007ffff1917e35 in SC_execute (self=0x64cd80) at statement.c:2006

#7  0x00007ffff18f2193 in Exec_with_parameters_resolved (stmt=0x64cd80, exec_end=0x7fffffff7248) at execute.c:448

#8  0x00007ffff18f3cdf in PGAPI_Execute (hstmt=0x64cd80, flag=0) at execute.c:1077

#9  0x00007ffff18f1ae8 in PGAPI_ExecDirect (hstmt=0x64cd80, szSqlStr=0x64c766 "SET extra_float_digits = 2", cbSqlStr=-3, flag=0) at execute.c:196

#10 0x00007ffff18df8ad in CC_send_settings (self=0x647490, set_query=0x7ffff19338b8 "SET DateStyle = 'ISO';SET extra_float_digits = 2") at connection.c:2178

#11 0x00007ffff18dcb15 in LIBPQ_CC_connect (self=0x647490, salt_para=0x7fffffff7440 "") at connection.c:1005

#12 0x00007ffff18dcb8e in CC_connect (self=0x647490, salt_para=0x7fffffff7440 "") at connection.c:1021

#13 0x00007ffff18efcbd in PGAPI_DriverConnect (hdbc=0x647490, hwnd=0x0,

    szConnStrIn=0x619710 "Driver=PostgreSQL;Server=192.168.1.3;Port=5433;Database=DBTestPostgres;Uid=_nokfssystestpostgres;ReadOnly=No;", cbConnStrIn=-3,

    szConnStrOut=0x7fffffffa170 "", cbConnStrOutMax=2048, pcbConnStrOut=0x0, fDriverCompletion=1) at drvconn.c:221

#14 0x00007ffff1920964 in SQLDriverConnect (hdbc=0x647490, hwnd=0x0,

    szConnStrIn=0x619710 "Driver=PostgreSQL;Server=192.168.1.3;Port=5433;Database=DBTestPostgres;Uid=_nokfssystestpostgres;ReadOnly=No;", cbConnStrIn=-3,

    szConnStrOut=0x7fffffffa170 "", cbConnStrOutMax=2048, pcbConnStrOut=0x0, fDriverCompletion=1) at odbcapi.c:190

#15 0x00007ffff775c309 in SQLDriverConnect () from /usr/lib64/libodbc.so.2

 

And check the function “handle_pgres_error”:

……

        if (PQstatus(self->pqconn) == CONNECTION_BAD)

        {

                CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_ERROR);

                abort_opt = CONN_DEAD;

        }

        else

        {

                CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);

                if (fatal && CC_is_in_trans(self))

                        CC_set_in_error_trans(self);

        }

…..

 

It’s that to say, during the client was ready to connect to postgres server, fast shutdown the postgres server will result to the client receive the notice that from the server. The client will set error number, but not set the error message, it will cause the client crash when call “strdup” which not judge the error message whether it is null.

So this is a bug in this version.

 

And then I have check the newest version of psqlodbc and found that “CC_connect” and “handle_pgres_error”, it is also have this issue.

 

The following code is the part of version: psqlodbc-09.06.0410.

Part of function “CC_connect”:

……

        if (CC_get_errornumber(self) > 0)

                saverr = strdup(CC_get_errormsg(self));

        CC_clear_error(self);                   /* clear any error */

        CC_lookup_lo(self);                     /* a hack to get the oid of

……

 


Part of function “handle_pgres_error”:

 

……

        /*

        *      If the error is continuable after rollback?

        */

        if (PQstatus(self->pqconn) == CONNECTION_BAD)

        {

                CC_set_errornumber(self, CONNECTION_COMMUNICATION_ERROR);

                CC_on_abort(self, CONN_DEAD); /* give up the connection */

        }

        else if ((errseverity_nonloc && strcmp(errseverity_nonloc, "FATAL") == 0) ||

                (NULL == errseverity_nonloc && errseverity && strcmp(errseverity, "FATAL") == 0)) /* no */

        {

                CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_SEVERITY_FATAL);

                CC_on_abort(self, CONN_DEAD); /* give up the connection */

        }

        else /* yes */

        {

                CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_SEVERITY_ERROR);

                if (CC_is_in_trans(self))

                        CC_set_in_error_trans(self);

        }

……

 

 

 

The newest version of psqlodbcw also have this issue, could you help to check this issue and correct it ? If you have any correction of that, please reply me, it’s important to us to receive your reply.

The attachment is the odbc driver debug log.

 

Best regards,
Dinghaiqiang


 

Attachment

pgsql-odbc by date:

Previous
From: "Ding, Haiqiang (NSB - CN/Hangzhou)"
Date:
Subject: [ODBC] The psqlodbcw.so will be crashed during connect to postgres server
Next
From: "Inoue, Hiroshi"
Date:
Subject: Re: [ODBC] The psqlodbcw.so will be crashed during connect topostgres server