1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-02 11:44:50 +03:00

Parse more strictly integer parameters from connection strings in libpq

The following parameters have been parsed in lossy ways when specified
in a connection string processed by libpq:
- connect_timeout
- keepalives
- keepalives_count
- keepalives_idle
- keepalives_interval
- port

Overflowing values or the presence of incorrect characters were not
properly checked, leading to libpq trying to use such values and fail
with unhelpful error messages.  This commit hardens the parsing of those
parameters so as it is possible to find easily incorrect values.

Author: Fabien Coelho
Reviewed-by: Peter Eisentraut, Michael Paquier
Discussion: https://postgr.es/m/alpine.DEB.2.21.1808171206180.20841@lancre
This commit is contained in:
Michael Paquier 2018-09-12 06:46:01 +09:00
parent 0d45cd96fd
commit e7a2217978

View File

@ -1587,6 +1587,34 @@ useKeepalives(PGconn *conn)
return val != 0 ? 1 : 0;
}
/*
* Parse and try to interpret "value" as an integer value, and if successful,
* store it in *result, complaining if there is any trailing garbage or an
* overflow.
*/
static bool
parse_int_param(const char *value, int *result, PGconn *conn,
const char *context)
{
char *end;
long numval;
*result = 0;
errno = 0;
numval = strtol(value, &end, 10);
if (errno == 0 && *end == '\0' && numval == (int) numval)
{
*result = numval;
return true;
}
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid integer value \"%s\" for keyword \"%s\"\n"),
value, context);
return false;
}
#ifndef WIN32
/*
* Set the keepalive idle timer.
@ -1599,7 +1627,9 @@ setKeepalivesIdle(PGconn *conn)
if (conn->keepalives_idle == NULL)
return 1;
idle = atoi(conn->keepalives_idle);
if (!parse_int_param(conn->keepalives_idle, &idle, conn,
"keepalives_idle"))
return 0;
if (idle < 0)
idle = 0;
@ -1631,7 +1661,9 @@ setKeepalivesInterval(PGconn *conn)
if (conn->keepalives_interval == NULL)
return 1;
interval = atoi(conn->keepalives_interval);
if (!parse_int_param(conn->keepalives_interval, &interval, conn,
"keepalives_interval"))
return 0;
if (interval < 0)
interval = 0;
@ -1664,7 +1696,9 @@ setKeepalivesCount(PGconn *conn)
if (conn->keepalives_count == NULL)
return 1;
count = atoi(conn->keepalives_count);
if (!parse_int_param(conn->keepalives_count, &count, conn,
"keepalives_count"))
return 0;
if (count < 0)
count = 0;
@ -1698,13 +1732,17 @@ setKeepalivesWin32(PGconn *conn)
int idle = 0;
int interval = 0;
if (conn->keepalives_idle)
idle = atoi(conn->keepalives_idle);
if (conn->keepalives_idle &&
!parse_int_param(conn->keepalives_idle, &idle, conn,
"keepalives_idle"))
return 0;
if (idle <= 0)
idle = 2 * 60 * 60; /* 2 hours = default */
if (conn->keepalives_interval)
interval = atoi(conn->keepalives_interval);
if (conn->keepalives_interval &&
!parse_int_param(conn->keepalives_interval, &interval, conn,
"keepalives_interval"))
return 0;
if (interval <= 0)
interval = 1; /* 1 second = default */
@ -1831,7 +1869,10 @@ connectDBComplete(PGconn *conn)
*/
if (conn->connect_timeout != NULL)
{
timeout = atoi(conn->connect_timeout);
if (!parse_int_param(conn->connect_timeout, &timeout, conn,
"connect_timeout"))
return 0;
if (timeout > 0)
{
/*
@ -1842,6 +1883,8 @@ connectDBComplete(PGconn *conn)
if (timeout < 2)
timeout = 2;
}
else /* negative means 0 */
timeout = 0;
}
for (;;)
@ -2108,7 +2151,9 @@ keep_going: /* We will come back to here until there is
thisport = DEF_PGPORT;
else
{
thisport = atoi(ch->port);
if (!parse_int_param(ch->port, &thisport, conn, "port"))
goto error_return;
if (thisport < 1 || thisport > 65535)
{
appendPQExpBuffer(&conn->errorMessage,