Re: BUG #5697: Infinite loop inside PQexecStart function - Mailing list pgsql-bugs

From Boris Bondarenko
Subject Re: BUG #5697: Infinite loop inside PQexecStart function
Date
Msg-id 4CADEC88.9040308@nyc.yamaha.com
Whole thread Raw
In response to Re: BUG #5697: Infinite loop inside PQexecStart function  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-bugs
That was a short form i used to point out the issue, the actual code
from  src/interfaces/libpq/fe-exec.c

    1368 static bool
    1369 PQexecStart(PGconn *conn)
    1370 {
    1371         PGresult   *result;
    1372
    1373         if (!conn)
    1374                 return false;
    1375
    1376         /*
    1377          * Silently discard any prior query result that
application didn't eat.
    1378          * This is probably poor design, but it's here for
backward compatibility.
    1379          */
    1380         while ((result = PQgetResult(conn)) != NULL)
    1381         {
    1382                 ExecStatusType resultStatus = result->resultStatus;
    1383
    1384                 PQclear(result);                /* only need
its status */
    1385                 if (resultStatus == PGRES_COPY_IN)
    1386                 {
    1387                         if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
    1388                         {
    1389                                 /* In protocol 3, we can get
out of a COPY IN state */
    1390                                 if (PQputCopyEnd(conn,
    1391
libpq_gettext("COPY terminated by new PQexec")) < 0)
    1392                                         return false;
    1393                                 /* keep waiting to swallow the
copy's failure message */
    1394                         }
    1395                         else
    1396                         {
    1397                                 /* In older protocols we have
to punt */
    1398
printfPQExpBuffer(&conn->errorMessage,
    1399                                   libpq_gettext("COPY IN state
must be terminated first\n"));
    1400                                 return false;
    1401                         }
    1402                 }
    1403                 else if (resultStatus == PGRES_COPY_OUT)
    1404                 {
    1405                         if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
    1406                         {
    1407                                 /*
    1408                                  * In protocol 3, we can get
out of a COPY OUT state: we just
    1409                                  * switch back to BUSY and
allow the remaining COPY data to be
    1410                                  * dropped on the floor.
    1411                                  */
    1412                                 conn->asyncStatus = PGASYNC_BUSY;
    1413                                 /* keep waiting to swallow the
copy's completion message */
    1414                         }
    1415                         else
    1416                         {
    1417                                 /* In older protocols we have
to punt */
    1418
printfPQExpBuffer(&conn->errorMessage,
    1419                                  libpq_gettext("COPY OUT state
must be terminated first\n"));
    1420                                 return false;
    1421                         }
    1422                 }
    1423                 /* check for loss of connection, too */
    1424                 if (conn->status == CONNECTION_BAD)
    1425                         return false;
    1426         }
    1427
    1428         /* OK to send a command */
    1429         return true;
    1430 }


Sorry for the confusion from the shortened form.


Tom Lane wrote:
> "Boris" <admin@nyc.yamaha.com> writes:
>> while ((result = PQgetResult(conn)) != NULL){
>>     ExecStatusType resultStatus = result->resultStatus;
>>     PQclear(result); /* only need its status */
>>     /* check for loss of connection, too */
>>     if (result->resultStatus == PGRES_COPY_IN ||
>>                          result->resultStatus == PGRES_COPY_OUT ||
>>                          conn->status == CONNECTION_BAD)
>>                          break;
>>     }
>
> This code is broken: once you've done PQclear() it's unsafe to access
> the PGresult.  I think you meant just "resultStatus" not
> "result->resultStatus" in the if().
>
>             regards, tom lane
>

--
Boris Bondarenko -:- bbondarenko@nyc.yamaha.com
    Yamaha Music Interactive Inc.

YMIA

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: BUG #5697: Infinite loop inside PQexecStart function
Next
From: Magnus Hagander
Date:
Subject: Re: BUG #5687: RADIUS Authentication issues