@@ -3214,28 +3214,46 @@ PQconnectPoll(PGconn *conn)
32143214
32153215 /*
32163216 * Try to validate message length before using it.
3217+ *
32173218 * Authentication requests can't be very large, although GSS
32183219 * auth requests may not be that small. Same for
3219- * NegotiateProtocolVersion. Errors can be a
3220- * little larger, but not huge. If we see a large apparent
3221- * length in an error, it means we're really talking to a
3222- * pre-3.0-protocol server; cope. (Before version 14, the
3223- * server also used the old protocol for errors that happened
3224- * before processing the startup packet.)
3220+ * NegotiateProtocolVersion.
3221+ *
3222+ * Errors can be a little larger, but not huge. If we see a
3223+ * large apparent length in an error, it means we're really
3224+ * talking to a pre-3.0-protocol server; cope. (Before
3225+ * version 14, the server also used the old protocol for
3226+ * errors that happened before processing the startup packet.)
32253227 */
3226- if (( beresp == 'R' || beresp == 'v' ) && (msgLength < 8 || msgLength > 2000 ))
3228+ if (beresp == 'R' && (msgLength < 8 || msgLength > 2000 ))
32273229 {
3228- libpq_append_conn_error (conn , "expected authentication request from server, but received %c" ,
3229- beresp );
3230+ libpq_append_conn_error (conn , "received invalid authentication request" );
3231+ goto error_return ;
3232+ }
3233+ if (beresp == 'v' && (msgLength < 8 || msgLength > 2000 ))
3234+ {
3235+ libpq_append_conn_error (conn , "received invalid protocol negotiation message" );
32303236 goto error_return ;
32313237 }
32323238
3233- if (beresp == 'E' && (msgLength < 8 || msgLength > 30000 ))
3239+ #define MAX_ERRLEN 30000
3240+ if (beresp == 'E' && (msgLength < 8 || msgLength > MAX_ERRLEN ))
32343241 {
32353242 /* Handle error from a pre-3.0 server */
32363243 conn -> inCursor = conn -> inStart + 1 ; /* reread data */
32373244 if (pqGets_append (& conn -> errorMessage , conn ))
32383245 {
3246+ /*
3247+ * We may not have authenticated the server yet, so
3248+ * don't let the buffer grow forever.
3249+ */
3250+ avail = conn -> inEnd - conn -> inCursor ;
3251+ if (avail > MAX_ERRLEN )
3252+ {
3253+ libpq_append_conn_error (conn , "received invalid error message" );
3254+ goto error_return ;
3255+ }
3256+
32393257 /* We'll come back when there is more data */
32403258 return PGRES_POLLING_READING ;
32413259 }
@@ -3255,9 +3273,15 @@ PQconnectPoll(PGconn *conn)
32553273
32563274 goto error_return ;
32573275 }
3276+ #undef MAX_ERRLEN
32583277
32593278 /*
32603279 * Can't process if message body isn't all here yet.
3280+ *
3281+ * After this check passes, any further EOF during parsing
3282+ * implies that the server sent a bad/truncated message.
3283+ * Reading more bytes won't help in that case, so don't return
3284+ * PGRES_POLLING_READING after this point.
32613285 */
32623286 msgLength -= 4 ;
32633287 avail = conn -> inEnd - conn -> inCursor ;
@@ -3280,8 +3304,8 @@ PQconnectPoll(PGconn *conn)
32803304 {
32813305 if (pqGetErrorNotice3 (conn , true))
32823306 {
3283- /* We'll come back when there is more data */
3284- return PGRES_POLLING_READING ;
3307+ libpq_append_conn_error ( conn , "received invalid error message" );
3308+ goto error_return ;
32853309 }
32863310 /* OK, we read the message; mark data consumed */
32873311 conn -> inStart = conn -> inCursor ;
@@ -3357,6 +3381,7 @@ PQconnectPoll(PGconn *conn)
33573381 {
33583382 if (pqGetNegotiateProtocolVersion3 (conn ))
33593383 {
3384+ libpq_append_conn_error (conn , "received invalid protocol negotiation message" );
33603385 goto error_return ;
33613386 }
33623387 /* OK, we read the message; mark data consumed */
@@ -3370,6 +3395,8 @@ PQconnectPoll(PGconn *conn)
33703395 /* Get the type of request. */
33713396 if (pqGetInt ((int * ) & areq , 4 , conn ))
33723397 {
3398+ /* can't happen because we checked the length already */
3399+ libpq_append_conn_error (conn , "received invalid authentication request" );
33733400 goto error_return ;
33743401 }
33753402 msgLength -= 4 ;
0 commit comments