Add some code to ensure that we don't lose communication sync due to
an oversize message, per suggestion from Oliver Jowett. I'm a bit dubious that this is a real problem, since the client likely doesn't have any more space available than the server, but it's not hard to make it behave according to the protocol intention.
This commit is contained in:
parent
6e53f18b84
commit
c77d06633a
@ -30,7 +30,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.172 2004/09/26 00:26:19 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.173 2004/10/18 23:23:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -777,6 +777,36 @@ pq_getbytes(char *s, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------
|
||||||
|
* pq_discardbytes - throw away a known number of bytes
|
||||||
|
*
|
||||||
|
* same as pq_getbytes except we do not copy the data to anyplace.
|
||||||
|
* this is used for resynchronizing after read errors.
|
||||||
|
*
|
||||||
|
* returns 0 if OK, EOF if trouble
|
||||||
|
* --------------------------------
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pq_discardbytes(size_t len)
|
||||||
|
{
|
||||||
|
size_t amount;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
while (PqRecvPointer >= PqRecvLength)
|
||||||
|
{
|
||||||
|
if (pq_recvbuf()) /* If nothing in buffer, then recv some */
|
||||||
|
return EOF; /* Failed to recv data */
|
||||||
|
}
|
||||||
|
amount = PqRecvLength - PqRecvPointer;
|
||||||
|
if (amount > len)
|
||||||
|
amount = len;
|
||||||
|
PqRecvPointer += amount;
|
||||||
|
len -= amount;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
* pq_getstring - get a null terminated string from connection
|
* pq_getstring - get a null terminated string from connection
|
||||||
*
|
*
|
||||||
@ -867,9 +897,8 @@ pq_getmessage(StringInfo s, int maxlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = ntohl(len);
|
len = ntohl(len);
|
||||||
len -= 4; /* discount length itself */
|
|
||||||
|
|
||||||
if (len < 0 ||
|
if (len < 4 ||
|
||||||
(maxlen > 0 && len > maxlen))
|
(maxlen > 0 && len > maxlen))
|
||||||
{
|
{
|
||||||
ereport(COMMERROR,
|
ereport(COMMERROR,
|
||||||
@ -878,10 +907,28 @@ pq_getmessage(StringInfo s, int maxlen)
|
|||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len -= 4; /* discount length itself */
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
/* Allocate space for message */
|
/*
|
||||||
enlargeStringInfo(s, len);
|
* Allocate space for message. If we run out of room (ridiculously
|
||||||
|
* large message), we will elog(ERROR), but we want to discard the
|
||||||
|
* message body so as not to lose communication sync.
|
||||||
|
*/
|
||||||
|
PG_TRY();
|
||||||
|
{
|
||||||
|
enlargeStringInfo(s, len);
|
||||||
|
}
|
||||||
|
PG_CATCH();
|
||||||
|
{
|
||||||
|
if (pq_discardbytes(len) == EOF)
|
||||||
|
ereport(COMMERROR,
|
||||||
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
||||||
|
errmsg("incomplete message from client")));
|
||||||
|
PG_RE_THROW();
|
||||||
|
}
|
||||||
|
PG_END_TRY();
|
||||||
|
|
||||||
/* And grab the message */
|
/* And grab the message */
|
||||||
if (pq_getbytes(s->data, len) == EOF)
|
if (pq_getbytes(s->data, len) == EOF)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user