libpq-strict-atoi-2.patch
text/x-diff
Filename: libpq-strict-atoi-2.patch
Type: text/x-diff
Part: 0
Message:
Re: libpq stricter integer parsing
Patch
Format: unified
| File | + | − |
|---|---|---|
| doc/src/sgml/libpq.sgml | 10 | 0 |
| src/interfaces/libpq/fe-connect.c | 54 | 9 |
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 5e7931ba90..a6cbbea655 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1591,6 +1591,16 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
</varlistentry>
</variablelist>
</para>
+
+ <para>
+ Integer values expected for keywords <literal>port</literal>,
+ <literal>connect_timeout</literal>,
+ <literal>keepalives_idle</literal>,
+ <literal>keepalives_interval</literal> and
+ <literal>keepalives_timeout</literal> are parsed strictly.
+ Versions of <application>libpq</application> before
+ <product>PostgreSQL 12</product> accepted trailing garbage or overflows.
+ </para>
</sect2>
</sect1>
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index db5aacd0e9..5ea51d5c55 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -1586,6 +1586,35 @@ useKeepalives(PGconn *conn)
return val != 0 ? 1 : 0;
}
+/*
+ * Parse integer, report any syntax error, and tell if all is well.
+ */
+static bool
+strict_atoi(const char *str, int *val, PGconn *conn, const char *context)
+{
+ char *endptr;
+
+ errno = 0;
+ *val = strtol(str, &endptr, 10);
+
+ if (errno != 0)
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("invalid integer \"%s\" for keyword \"%s\": %s\n"),
+ str, context, strerror(errno));
+ return false;
+ }
+ else if (*endptr != '\0')
+ {
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("invalid integer \"%s\" for keyword \"%s\": trailing garbage\n"),
+ str, context);
+ return false;
+ }
+
+ return true;
+}
+
#ifndef WIN32
/*
* Set the keepalive idle timer.
@@ -1598,7 +1627,9 @@ setKeepalivesIdle(PGconn *conn)
if (conn->keepalives_idle == NULL)
return 1;
- idle = atoi(conn->keepalives_idle);
+ if (!strict_atoi(conn->keepalives_idle, &idle, conn, "keepalives_idle"))
+ return 0;
+
if (idle < 0)
idle = 0;
@@ -1630,7 +1661,9 @@ setKeepalivesInterval(PGconn *conn)
if (conn->keepalives_interval == NULL)
return 1;
- interval = atoi(conn->keepalives_interval);
+ if (!strict_atoi(conn->keepalives_interval, &interval, conn, "keepalives_interval"))
+ return 0;
+
if (interval < 0)
interval = 0;
@@ -1663,7 +1696,9 @@ setKeepalivesCount(PGconn *conn)
if (conn->keepalives_count == NULL)
return 1;
- count = atoi(conn->keepalives_count);
+ if (!strict_atoi(conn->keepalives_count, &count, conn, "keepalives_count"))
+ return 0;
+
if (count < 0)
count = 0;
@@ -1697,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 &&
+ !strict_atoi(conn->keepalives_idle, &idle, conn, "keepalives_idle"))
+ return 0;
+
+ if (conn->keepalives_interval &&
+ !strict_atoi(conn->keepalives_interval, &interval, conn, "keepalives_interval"))
+ return 0;
+
if (idle <= 0)
idle = 2 * 60 * 60; /* 2 hours = default */
- if (conn->keepalives_interval)
- interval = atoi(conn->keepalives_interval);
if (interval <= 0)
interval = 1; /* 1 second = default */
@@ -1817,7 +1856,9 @@ connectDBComplete(PGconn *conn)
*/
if (conn->connect_timeout != NULL)
{
- timeout = atoi(conn->connect_timeout);
+ if (!strict_atoi(conn->connect_timeout, &timeout, conn, "connect_timeout"))
+ return 0;
+
if (timeout > 0)
{
/*
@@ -1828,6 +1869,8 @@ connectDBComplete(PGconn *conn)
if (timeout < 2)
timeout = 2;
}
+ else /* negative means 0 */
+ timeout = 0;
}
for (;;)
@@ -2094,7 +2137,9 @@ keep_going: /* We will come back to here until there is
thisport = DEF_PGPORT;
else
{
- thisport = atoi(ch->port);
+ if (!strict_atoi(ch->port, &thisport, conn, "port"))
+ goto error_return;
+
if (thisport < 1 || thisport > 65535)
{
appendPQExpBuffer(&conn->errorMessage,