diff options
author | Michael Paquier <michael@paquier.xyz> | 2018-09-12 06:46:01 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2018-09-12 06:46:01 +0900 |
commit | e7a2217978d9cbb2149bfcb4ef1e45716cfcbefb (patch) | |
tree | 284ebcfa72befbbab4c67950c85ce93902d7842e /src | |
parent | 0d45cd96fd0f3387d1bcf7e6f873c73c4f251df8 (diff) | |
download | postgresql-e7a2217978d9cbb2149bfcb4ef1e45716cfcbefb.tar.gz postgresql-e7a2217978d9cbb2149bfcb4ef1e45716cfcbefb.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 63 |
1 files changed, 54 insertions, 9 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 42cdb971a37..45bc067921c 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -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, |