]> granicus.if.org Git - postgresql/commitdiff
Fix parsing of integer values for connection parameters in libpq
authorMichael Paquier <michael@paquier.xyz>
Mon, 21 Oct 2019 02:17:43 +0000 (11:17 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 21 Oct 2019 02:17:43 +0000 (11:17 +0900)
Commit e7a2217 has introduced stricter checks for integer values in
connection parameters for libpq.  However this failed to correctly check
after trailing whitespaces, while leading whitespaces were discarded per
the use of strtol(3).  This fixes and refactors the parsing logic to
handle both cases consistently.  Note that trying to restrict the use of
trailing whitespaces can easily break connection strings like in ECPG
regression tests (these have allowed me to catch the parsing bug with
connect_timeout).

Author: Michael Paquier
Reviewed-by: Lars Kanis
Discussion: https://postgr.es/m/a9b4cbd7-4ecb-06b2-ebd7-1739bbff3217@greiz-reinsdorf.de
Backpatch-through: 12

src/interfaces/libpq/fe-connect.c

index a7eab9a4af256b0c60d8b186a39af0926dc1ab13..957b9d26c132d488d30458847b459715982f5feb 100644 (file)
@@ -1654,7 +1654,7 @@ useKeepalives(PGconn *conn)
 /*
  * 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.
+ * overflow.  This allows any number of leading and trailing whitespaces.
  */
 static bool
 parse_int_param(const char *value, int *result, PGconn *conn,
@@ -1665,14 +1665,31 @@ parse_int_param(const char *value, int *result, PGconn *conn,
 
        *result = 0;
 
+       /* strtol(3) skips leading whitespaces */
        errno = 0;
        numval = strtol(value, &end, 10);
-       if (errno == 0 && *end == '\0' && numval == (int) numval)
-       {
-               *result = numval;
-               return true;
-       }
 
+       /*
+        * If no progress was done during the parsing or an error happened, fail.
+        * This tests properly for overflows of the result.
+        */
+       if (value == end || errno != 0 || numval != (int) numval)
+               goto error;
+
+       /*
+        * Skip any trailing whitespace; if anything but whitespace remains before
+        * the terminating character, fail
+        */
+       while (*end && *end != '\0' && isspace((unsigned char) *end))
+               end++;
+
+       if (*end && *end != '\0')
+               goto error;
+
+       *result = numval;
+       return true;
+
+error:
        appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
                                          value, context);