@@ -3214,28 +3214,46 @@ PQconnectPoll(PGconn *conn)
3214
3214
3215
3215
/*
3216
3216
* Try to validate message length before using it.
3217
+ *
3217
3218
* Authentication requests can't be very large, although GSS
3218
3219
* 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.)
3225
3227
*/
3226
- if (( beresp == 'R' || beresp == 'v' ) && (msgLength < 8 || msgLength > 2000 ))
3228
+ if (beresp == 'R' && (msgLength < 8 || msgLength > 2000 ))
3227
3229
{
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" );
3230
3236
goto error_return ;
3231
3237
}
3232
3238
3233
- if (beresp == 'E' && (msgLength < 8 || msgLength > 30000 ))
3239
+ #define MAX_ERRLEN 30000
3240
+ if (beresp == 'E' && (msgLength < 8 || msgLength > MAX_ERRLEN ))
3234
3241
{
3235
3242
/* Handle error from a pre-3.0 server */
3236
3243
conn -> inCursor = conn -> inStart + 1 ; /* reread data */
3237
3244
if (pqGets_append (& conn -> errorMessage , conn ))
3238
3245
{
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
+
3239
3257
/* We'll come back when there is more data */
3240
3258
return PGRES_POLLING_READING ;
3241
3259
}
@@ -3255,9 +3273,15 @@ PQconnectPoll(PGconn *conn)
3255
3273
3256
3274
goto error_return ;
3257
3275
}
3276
+ #undef MAX_ERRLEN
3258
3277
3259
3278
/*
3260
3279
* 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.
3261
3285
*/
3262
3286
msgLength -= 4 ;
3263
3287
avail = conn -> inEnd - conn -> inCursor ;
@@ -3280,8 +3304,8 @@ PQconnectPoll(PGconn *conn)
3280
3304
{
3281
3305
if (pqGetErrorNotice3 (conn , true))
3282
3306
{
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 ;
3285
3309
}
3286
3310
/* OK, we read the message; mark data consumed */
3287
3311
conn -> inStart = conn -> inCursor ;
@@ -3357,6 +3381,7 @@ PQconnectPoll(PGconn *conn)
3357
3381
{
3358
3382
if (pqGetNegotiateProtocolVersion3 (conn ))
3359
3383
{
3384
+ libpq_append_conn_error (conn , "received invalid protocol negotiation message" );
3360
3385
goto error_return ;
3361
3386
}
3362
3387
/* OK, we read the message; mark data consumed */
@@ -3370,6 +3395,8 @@ PQconnectPoll(PGconn *conn)
3370
3395
/* Get the type of request. */
3371
3396
if (pqGetInt ((int * ) & areq , 4 , conn ))
3372
3397
{
3398
+ /* can't happen because we checked the length already */
3399
+ libpq_append_conn_error (conn , "received invalid authentication request" );
3373
3400
goto error_return ;
3374
3401
}
3375
3402
msgLength -= 4 ;
0 commit comments