Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit51c54bb

Browse files
committed
Re-simplify management of inStart in pqParseInput3's subroutines.
Commit92785da copied some logic related to advancement of inStartfrom pqParseInput3 into getRowDescriptions and getAnotherTuple,because it wanted to allow user-defined row processor callbacks topotentially longjmp out of the library, and inStart would have to beupdated before that happened to avoid an infinite loop. We laterdecided that that API was impossibly fragile and reverted it, butwe didn't undo all of the related code changes, and this bit ofmessiness survived. Undo it now so that there's just one place inpqParseInput3's processing where inStart is advanced; this willsimplify addition of better tracing support.getParamDescriptions had grown similar processing somewhere alongthe way (not in92785da; I didn't track down just when), but it'sactually buggy because its handling of corrupt-message cases seems tohave been copied from the v2 logic where we lacked a known messagelength. The cases where we "goto not_enough_data" should not simplyreturn EOF, because then we won't consume the message, potentiallycreating an infinite loop. That situation now represents adefinitively corrupt message, and we should report it as such.Although no field reports of getParamDescriptions getting stuck ina loop have been seen, it seems appropriate to back-patch that fix.I chose to back-patch all of this to keep the logic looking more alikein supported branches.Discussion:https://postgr.es/m/2217283.1615411989@sss.pgh.pa.us
1 parentf71519e commit51c54bb

File tree

1 file changed

+23
-57
lines changed

1 file changed

+23
-57
lines changed

‎src/interfaces/libpq/fe-protocol3.c

Lines changed: 23 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,6 @@ pqParseInput3(PGconn *conn)
290290
/* First 'T' in a query sequence */
291291
if (getRowDescriptions(conn,msgLength))
292292
return;
293-
/* getRowDescriptions() moves inStart itself */
294-
continue;
295293
}
296294
else
297295
{
@@ -337,17 +335,14 @@ pqParseInput3(PGconn *conn)
337335
case't':/* Parameter Description */
338336
if (getParamDescriptions(conn,msgLength))
339337
return;
340-
/* getParamDescriptions() moves inStart itself */
341-
continue;
338+
break;
342339
case'D':/* Data Row */
343340
if (conn->result!=NULL&&
344341
conn->result->resultStatus==PGRES_TUPLES_OK)
345342
{
346343
/* Read another tuple of a normal query response */
347344
if (getAnotherTuple(conn,msgLength))
348345
return;
349-
/* getAnotherTuple() moves inStart itself */
350-
continue;
351346
}
352347
elseif (conn->result!=NULL&&
353348
conn->result->resultStatus==PGRES_FATAL_ERROR)
@@ -462,7 +457,6 @@ handleSyncLoss(PGconn *conn, char id, int msgLength)
462457
* command for a prepared statement) containing the attribute data.
463458
* Returns: 0 if processed message successfully, EOF to suspend parsing
464459
* (the latter case is not actually used currently).
465-
* In the former case, conn->inStart has been advanced past the message.
466460
*/
467461
staticint
468462
getRowDescriptions(PGconn*conn,intmsgLength)
@@ -567,19 +561,9 @@ getRowDescriptions(PGconn *conn, int msgLength)
567561
result->binary=0;
568562
}
569563

570-
/* Sanity check that we absorbed all the data */
571-
if (conn->inCursor!=conn->inStart+5+msgLength)
572-
{
573-
errmsg=libpq_gettext("extraneous data in \"T\" message");
574-
gotoadvance_and_error;
575-
}
576-
577564
/* Success! */
578565
conn->result=result;
579566

580-
/* Advance inStart to show that the "T" message has been processed. */
581-
conn->inStart=conn->inCursor;
582-
583567
/*
584568
* If we're doing a Describe, we're done, and ready to pass the result
585569
* back to the client.
@@ -603,9 +587,6 @@ getRowDescriptions(PGconn *conn, int msgLength)
603587
if (result&&result!=conn->result)
604588
PQclear(result);
605589

606-
/* Discard the failed message by pretending we read it */
607-
conn->inStart+=5+msgLength;
608-
609590
/*
610591
* Replace partially constructed result with an error result. First
611592
* discard the old result to try to win back some memory.
@@ -624,6 +605,12 @@ getRowDescriptions(PGconn *conn, int msgLength)
624605
appendPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
625606
pqSaveErrorResult(conn);
626607

608+
/*
609+
* Show the message as fully consumed, else pqParseInput3 will overwrite
610+
* our error with a complaint about that.
611+
*/
612+
conn->inCursor=conn->inStart+5+msgLength;
613+
627614
/*
628615
* Return zero to allow input parsing to continue. Subsequent "D"
629616
* messages will be ignored until we get to end of data, since an error
@@ -635,12 +622,8 @@ getRowDescriptions(PGconn *conn, int msgLength)
635622
/*
636623
* parseInput subroutine to read a 't' (ParameterDescription) message.
637624
* We'll build a new PGresult structure containing the parameter data.
638-
* Returns: 0 if completed message, EOF if not enough data yet.
639-
* In the former case, conn->inStart has been advanced past the message.
640-
*
641-
* Note that if we run out of data, we have to release the partially
642-
* constructed PGresult, and rebuild it again next time. Fortunately,
643-
* that shouldn't happen often, since 't' messages usually fit in a packet.
625+
* Returns: 0 if processed message successfully, EOF to suspend parsing
626+
* (the latter case is not actually used currently).
644627
*/
645628
staticint
646629
getParamDescriptions(PGconn*conn,intmsgLength)
@@ -680,33 +663,19 @@ getParamDescriptions(PGconn *conn, int msgLength)
680663
result->paramDescs[i].typid=typid;
681664
}
682665

683-
/* Sanity check that we absorbed all the data */
684-
if (conn->inCursor!=conn->inStart+5+msgLength)
685-
{
686-
errmsg=libpq_gettext("extraneous data in \"t\" message");
687-
gotoadvance_and_error;
688-
}
689-
690666
/* Success! */
691667
conn->result=result;
692668

693-
/* Advance inStart to show that the "t" message has been processed. */
694-
conn->inStart=conn->inCursor;
695-
696669
return0;
697670

698671
not_enough_data:
699-
PQclear(result);
700-
returnEOF;
672+
errmsg=libpq_gettext("insufficient data in \"t\" message");
701673

702674
advance_and_error:
703675
/* Discard unsaved result, if any */
704676
if (result&&result!=conn->result)
705677
PQclear(result);
706678

707-
/* Discard the failed message by pretending we read it */
708-
conn->inStart+=5+msgLength;
709-
710679
/*
711680
* Replace partially constructed result with an error result. First
712681
* discard the old result to try to win back some memory.
@@ -724,6 +693,12 @@ getParamDescriptions(PGconn *conn, int msgLength)
724693
appendPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
725694
pqSaveErrorResult(conn);
726695

696+
/*
697+
* Show the message as fully consumed, else pqParseInput3 will overwrite
698+
* our error with a complaint about that.
699+
*/
700+
conn->inCursor=conn->inStart+5+msgLength;
701+
727702
/*
728703
* Return zero to allow input parsing to continue. Essentially, we've
729704
* replaced the COMMAND_OK result with an error result, but since this
@@ -737,7 +712,6 @@ getParamDescriptions(PGconn *conn, int msgLength)
737712
* We fill rowbuf with column pointers and then call the row processor.
738713
* Returns: 0 if processed message successfully, EOF to suspend parsing
739714
* (the latter case is not actually used currently).
740-
* In the former case, conn->inStart has been advanced past the message.
741715
*/
742716
staticint
743717
getAnotherTuple(PGconn*conn,intmsgLength)
@@ -810,28 +784,14 @@ getAnotherTuple(PGconn *conn, int msgLength)
810784
}
811785
}
812786

813-
/* Sanity check that we absorbed all the data */
814-
if (conn->inCursor!=conn->inStart+5+msgLength)
815-
{
816-
errmsg=libpq_gettext("extraneous data in \"D\" message");
817-
gotoadvance_and_error;
818-
}
819-
820-
/* Advance inStart to show that the "D" message has been processed. */
821-
conn->inStart=conn->inCursor;
822-
823787
/* Process the collected row */
824788
errmsg=NULL;
825789
if (pqRowProcessor(conn,&errmsg))
826790
return0;/* normal, successful exit */
827791

828-
gotoset_error_result;/* pqRowProcessor failed, report it */
792+
/* pqRowProcessor failed, fall through to report it */
829793

830794
advance_and_error:
831-
/* Discard the failed message by pretending we read it */
832-
conn->inStart+=5+msgLength;
833-
834-
set_error_result:
835795

836796
/*
837797
* Replace partially constructed result with an error result. First
@@ -851,6 +811,12 @@ getAnotherTuple(PGconn *conn, int msgLength)
851811
appendPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
852812
pqSaveErrorResult(conn);
853813

814+
/*
815+
* Show the message as fully consumed, else pqParseInput3 will overwrite
816+
* our error with a complaint about that.
817+
*/
818+
conn->inCursor=conn->inStart+5+msgLength;
819+
854820
/*
855821
* Return zero to allow input parsing to continue. Subsequent "D"
856822
* messages will be ignored until we get to end of data, since an error

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp