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)
777777 return 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
869899 len = ntohl (len );
870- len -= 4 ; /* discount length itself */
871900
872- if (len < 0 ||
901+ if (len < 4 ||
873902 (maxlen > 0 && len > maxlen ))
874903 {
875904 ereport (COMMERROR ,
@@ -878,10 +907,28 @@ pq_getmessage(StringInfo s, int maxlen)
878907 return EOF ;
879908 }
880909
910+ len -= 4 ; /* discount length itself */
911+
881912 if (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 */
887934 if (pq_getbytes (s -> data , len ) == EOF )
0 commit comments