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

Commit56defbd

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 parent1cc33ab commit56defbd

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
@@ -292,8 +292,6 @@ pqParseInput3(PGconn *conn)
292292
/* First 'T' in a query sequence */
293293
if (getRowDescriptions(conn,msgLength))
294294
return;
295-
/* getRowDescriptions() moves inStart itself */
296-
continue;
297295
}
298296
else
299297
{
@@ -339,17 +337,14 @@ pqParseInput3(PGconn *conn)
339337
case't':/* Parameter Description */
340338
if (getParamDescriptions(conn,msgLength))
341339
return;
342-
/* getParamDescriptions() moves inStart itself */
343-
continue;
340+
break;
344341
case'D':/* Data Row */
345342
if (conn->result!=NULL&&
346343
conn->result->resultStatus==PGRES_TUPLES_OK)
347344
{
348345
/* Read another tuple of a normal query response */
349346
if (getAnotherTuple(conn,msgLength))
350347
return;
351-
/* getAnotherTuple() moves inStart itself */
352-
continue;
353348
}
354349
elseif (conn->result!=NULL&&
355350
conn->result->resultStatus==PGRES_FATAL_ERROR)
@@ -466,7 +461,6 @@ handleSyncLoss(PGconn *conn, char id, int msgLength)
466461
* command for a prepared statement) containing the attribute data.
467462
* Returns: 0 if processed message successfully, EOF to suspend parsing
468463
* (the latter case is not actually used currently).
469-
* In the former case, conn->inStart has been advanced past the message.
470464
*/
471465
staticint
472466
getRowDescriptions(PGconn*conn,intmsgLength)
@@ -571,19 +565,9 @@ getRowDescriptions(PGconn *conn, int msgLength)
571565
result->binary=0;
572566
}
573567

574-
/* Sanity check that we absorbed all the data */
575-
if (conn->inCursor!=conn->inStart+5+msgLength)
576-
{
577-
errmsg=libpq_gettext("extraneous data in \"T\" message");
578-
gotoadvance_and_error;
579-
}
580-
581568
/* Success! */
582569
conn->result=result;
583570

584-
/* Advance inStart to show that the "T" message has been processed. */
585-
conn->inStart=conn->inCursor;
586-
587571
/*
588572
* If we're doing a Describe, we're done, and ready to pass the result
589573
* back to the client.
@@ -607,9 +591,6 @@ getRowDescriptions(PGconn *conn, int msgLength)
607591
if (result&&result!=conn->result)
608592
PQclear(result);
609593

610-
/* Discard the failed message by pretending we read it */
611-
conn->inStart+=5+msgLength;
612-
613594
/*
614595
* Replace partially constructed result with an error result. First
615596
* discard the old result to try to win back some memory.
@@ -628,6 +609,12 @@ getRowDescriptions(PGconn *conn, int msgLength)
628609
printfPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
629610
pqSaveErrorResult(conn);
630611

612+
/*
613+
* Show the message as fully consumed, else pqParseInput3 will overwrite
614+
* our error with a complaint about that.
615+
*/
616+
conn->inCursor=conn->inStart+5+msgLength;
617+
631618
/*
632619
* Return zero to allow input parsing to continue. Subsequent "D"
633620
* messages will be ignored until we get to end of data, since an error
@@ -639,12 +626,8 @@ getRowDescriptions(PGconn *conn, int msgLength)
639626
/*
640627
* parseInput subroutine to read a 't' (ParameterDescription) message.
641628
* We'll build a new PGresult structure containing the parameter data.
642-
* Returns: 0 if completed message, EOF if not enough data yet.
643-
* In the former case, conn->inStart has been advanced past the message.
644-
*
645-
* Note that if we run out of data, we have to release the partially
646-
* constructed PGresult, and rebuild it again next time. Fortunately,
647-
* that shouldn't happen often, since 't' messages usually fit in a packet.
629+
* Returns: 0 if processed message successfully, EOF to suspend parsing
630+
* (the latter case is not actually used currently).
648631
*/
649632
staticint
650633
getParamDescriptions(PGconn*conn,intmsgLength)
@@ -684,33 +667,19 @@ getParamDescriptions(PGconn *conn, int msgLength)
684667
result->paramDescs[i].typid=typid;
685668
}
686669

687-
/* Sanity check that we absorbed all the data */
688-
if (conn->inCursor!=conn->inStart+5+msgLength)
689-
{
690-
errmsg=libpq_gettext("extraneous data in \"t\" message");
691-
gotoadvance_and_error;
692-
}
693-
694670
/* Success! */
695671
conn->result=result;
696672

697-
/* Advance inStart to show that the "t" message has been processed. */
698-
conn->inStart=conn->inCursor;
699-
700673
return0;
701674

702675
not_enough_data:
703-
PQclear(result);
704-
returnEOF;
676+
errmsg=libpq_gettext("insufficient data in \"t\" message");
705677

706678
advance_and_error:
707679
/* Discard unsaved result, if any */
708680
if (result&&result!=conn->result)
709681
PQclear(result);
710682

711-
/* Discard the failed message by pretending we read it */
712-
conn->inStart+=5+msgLength;
713-
714683
/*
715684
* Replace partially constructed result with an error result. First
716685
* discard the old result to try to win back some memory.
@@ -728,6 +697,12 @@ getParamDescriptions(PGconn *conn, int msgLength)
728697
printfPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
729698
pqSaveErrorResult(conn);
730699

700+
/*
701+
* Show the message as fully consumed, else pqParseInput3 will overwrite
702+
* our error with a complaint about that.
703+
*/
704+
conn->inCursor=conn->inStart+5+msgLength;
705+
731706
/*
732707
* Return zero to allow input parsing to continue. Essentially, we've
733708
* replaced the COMMAND_OK result with an error result, but since this
@@ -741,7 +716,6 @@ getParamDescriptions(PGconn *conn, int msgLength)
741716
* We fill rowbuf with column pointers and then call the row processor.
742717
* Returns: 0 if processed message successfully, EOF to suspend parsing
743718
* (the latter case is not actually used currently).
744-
* In the former case, conn->inStart has been advanced past the message.
745719
*/
746720
staticint
747721
getAnotherTuple(PGconn*conn,intmsgLength)
@@ -814,28 +788,14 @@ getAnotherTuple(PGconn *conn, int msgLength)
814788
}
815789
}
816790

817-
/* Sanity check that we absorbed all the data */
818-
if (conn->inCursor!=conn->inStart+5+msgLength)
819-
{
820-
errmsg=libpq_gettext("extraneous data in \"D\" message");
821-
gotoadvance_and_error;
822-
}
823-
824-
/* Advance inStart to show that the "D" message has been processed. */
825-
conn->inStart=conn->inCursor;
826-
827791
/* Process the collected row */
828792
errmsg=NULL;
829793
if (pqRowProcessor(conn,&errmsg))
830794
return0;/* normal, successful exit */
831795

832-
gotoset_error_result;/* pqRowProcessor failed, report it */
796+
/* pqRowProcessor failed, fall through to report it */
833797

834798
advance_and_error:
835-
/* Discard the failed message by pretending we read it */
836-
conn->inStart+=5+msgLength;
837-
838-
set_error_result:
839799

840800
/*
841801
* Replace partially constructed result with an error result. First
@@ -855,6 +815,12 @@ getAnotherTuple(PGconn *conn, int msgLength)
855815
printfPQExpBuffer(&conn->errorMessage,"%s\n",errmsg);
856816
pqSaveErrorResult(conn);
857817

818+
/*
819+
* Show the message as fully consumed, else pqParseInput3 will overwrite
820+
* our error with a complaint about that.
821+
*/
822+
conn->inCursor=conn->inStart+5+msgLength;
823+
858824
/*
859825
* Return zero to allow input parsing to continue. Subsequent "D"
860826
* messages will be ignored until we get to end of data, since an error

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp