From 2eb3bc58814fa1ab86308a3658ddb76081080db3 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Thu, 5 Mar 2020 13:00:38 +0900 Subject: [PATCH] Fix issues around .pgpass file. 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 | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 408000af83a..0157c619aac 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -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);