Fix issues around .pgpass file.
authorFujii Masao <fujii@postgresql.org>
Thu, 5 Mar 2020 04:00:38 +0000 (13:00 +0900)
committerFujii Masao <fujii@postgresql.org>
Thu, 5 Mar 2020 04:00:38 +0000 (13:00 +0900)
This commit fixes the following two issues around .pgpass file.

(1) If the length of a line in .pgpass file was larger than 319B,
        libpq silently treated each 319B in the line as a separate
        setting line.

(2) The document explains that a line beginning with # is treated
        as a comment in .pgpass. But there was no code doing such
        special handling. Whether a line begins with # or not, libpq
        just checked that the first token in the line match with the host.

For (1), this commit makes libpq warn if the length of a line
is larger than 319B, and throw away the remaining part beginning
from 320B position.

For (2), this commit changes libpq so that it treats any lines
beginning with # as comments.

Author: Fujii Masao
Reviewed-by: Hamid Akhtar
Discussion: https://postgr.es/m/c0f0c01c-fa74-9749-2084-b73882fd5465@oss.nttdata.com

src/interfaces/libpq/fe-connect.c

index 408000af83aaae7ec1d5cf3be3a460cecaacc233..0157c619aac36cc964bd62e0c3d0081d8c7b120a 100644 (file)
@@ -6949,6 +6949,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
 {
        FILE       *fp;
        struct stat stat_buf;
+       int                     line_number = 0;
 
 #define LINELEN NAMEDATALEN*5
        char            buf[LINELEN];
@@ -7014,10 +7015,42 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
                                   *p1,
                                   *p2;
                int                     len;
+               int                     buflen;
 
                if (fgets(buf, sizeof(buf), fp) == NULL)
                        break;
 
+               line_number++;
+               buflen = strlen(buf);
+               if (buflen >= sizeof(buf) - 1 && buf[buflen - 1] != '\n')
+               {
+                       char            rest[LINELEN];
+                       int                     restlen;
+
+                       /*
+                        * Warn if this password setting line is too long, because it's
+                        * unexpectedly truncated.
+                        */
+                       if (buf[0] != '#')
+                               fprintf(stderr,
+                                               libpq_gettext("WARNING: line %d too long in password file \"%s\"\n"),
+                                               line_number, pgpassfile);
+
+                       /* eat rest of the line */
+                       while (!feof(fp) && !ferror(fp))
+                       {
+                               if (fgets(rest, sizeof(rest), fp) == NULL)
+                                       break;
+                               restlen = strlen(rest);
+                               if (restlen < sizeof(rest) - 1 || rest[restlen - 1] == '\n')
+                                       break;
+                       }
+               }
+
+               /* ignore comments */
+               if (buf[0] == '#')
+                       continue;
+
                /* strip trailing newline and carriage return */
                len = pg_strip_crlf(buf);