3030 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
3131 * Portions Copyright (c) 1994, Regents of the University of California
3232 *
33- *$PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.172 2004/09/26 00:26 :19 tgl Exp $
33+ *$PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.173 2004/10/18 23:23 :19 tgl Exp $
3434 *
3535 *-------------------------------------------------------------------------
3636 */
@@ -777,6 +777,36 @@ pq_getbytes(char *s, size_t len)
777777return 0 ;
778778}
779779
780+ /* --------------------------------
781+ *pq_discardbytes- throw away a known number of bytes
782+ *
783+ *same as pq_getbytes except we do not copy the data to anyplace.
784+ *this is used for resynchronizing after read errors.
785+ *
786+ *returns 0 if OK, EOF if trouble
787+ * --------------------------------
788+ */
789+ static int
790+ pq_discardbytes (size_t len )
791+ {
792+ size_t amount ;
793+
794+ while (len > 0 )
795+ {
796+ while (PqRecvPointer >=PqRecvLength )
797+ {
798+ if (pq_recvbuf ())/* If nothing in buffer, then recv some */
799+ return EOF ;/* Failed to recv data */
800+ }
801+ amount = PqRecvLength - PqRecvPointer ;
802+ if (amount > len )
803+ amount = len ;
804+ PqRecvPointer += amount ;
805+ len -= amount ;
806+ }
807+ return 0 ;
808+ }
809+
780810/* --------------------------------
781811 *pq_getstring- get a null terminated string from connection
782812 *
@@ -867,9 +897,8 @@ pq_getmessage(StringInfo s, int maxlen)
867897}
868898
869899len = ntohl (len );
870- len -= 4 ;/* discount length itself */
871900
872- if (len < 0 ||
901+ if (len < 4 ||
873902(maxlen > 0 && len > maxlen ))
874903{
875904ereport (COMMERROR ,
@@ -878,10 +907,28 @@ pq_getmessage(StringInfo s, int maxlen)
878907return EOF ;
879908}
880909
910+ len -= 4 ;/* discount length itself */
911+
881912if (len > 0 )
882913{
883- /* Allocate space for message */
884- enlargeStringInfo (s ,len );
914+ /*
915+ * Allocate space for message. If we run out of room (ridiculously
916+ * large message), we will elog(ERROR), but we want to discard the
917+ * message body so as not to lose communication sync.
918+ */
919+ PG_TRY ();
920+ {
921+ enlargeStringInfo (s ,len );
922+ }
923+ PG_CATCH ();
924+ {
925+ if (pq_discardbytes (len )== EOF )
926+ ereport (COMMERROR ,
927+ (errcode (ERRCODE_PROTOCOL_VIOLATION ),
928+ errmsg ("incomplete message from client" )));
929+ PG_RE_THROW ();
930+ }
931+ PG_END_TRY ();
885932
886933/* And grab the message */
887934if (pq_getbytes (s -> data ,len )== EOF )