{
    FILE       *fp;
    struct stat stat_buf;
-   int         line_number = 0;
-
-#define LINELEN NAMEDATALEN*5
-   char        buf[LINELEN];
+   PQExpBufferData buf;
 
    if (dbname == NULL || dbname[0] == '\0')
        return NULL;
    if (fp == NULL)
        return NULL;
 
+   /* Use an expansible buffer to accommodate any reasonable line length */
+   initPQExpBuffer(&buf);
+
    while (!feof(fp) && !ferror(fp))
    {
-       char       *t = buf,
-                  *ret,
-                  *p1,
-                  *p2;
-       int         len;
-       int         buflen;
+       /* Make sure there's a reasonable amount of room in the buffer */
+       if (!enlargePQExpBuffer(&buf, 128))
+           break;
 
-       if (fgets(buf, sizeof(buf), fp) == NULL)
+       /* Read some data, appending it to what we already have */
+       if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
            break;
+       buf.len += strlen(buf.data + buf.len);
 
-       line_number++;
-       buflen = strlen(buf);
-       if (buflen >= sizeof(buf) - 1 && buf[buflen - 1] != '\n')
+       /* If we don't yet have a whole line, loop around to read more */
+       if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
+           continue;
+
+       /* ignore comments */
+       if (buf.data[0] != '#')
        {
-           char        rest[LINELEN];
-           int         restlen;
+           char       *t = buf.data;
+           int         len;
 
-           /*
-            * 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);
+           /* strip trailing newline and carriage return */
+           len = pg_strip_crlf(t);
 
-           /* eat rest of the line */
-           while (!feof(fp) && !ferror(fp))
+           if (len > 0 &&
+               (t = pwdfMatchesString(t, hostname)) != NULL &&
+               (t = pwdfMatchesString(t, port)) != NULL &&
+               (t = pwdfMatchesString(t, dbname)) != NULL &&
+               (t = pwdfMatchesString(t, username)) != NULL)
            {
-               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);
+               /* Found a match. */
+               char       *ret,
+                          *p1,
+                          *p2;
 
-       if (len == 0)
-           continue;
+               ret = strdup(t);
 
-       if ((t = pwdfMatchesString(t, hostname)) == NULL ||
-           (t = pwdfMatchesString(t, port)) == NULL ||
-           (t = pwdfMatchesString(t, dbname)) == NULL ||
-           (t = pwdfMatchesString(t, username)) == NULL)
-           continue;
+               fclose(fp);
+               explicit_bzero(buf.data, buf.maxlen);
+               termPQExpBuffer(&buf);
 
-       /* Found a match. */
-       ret = strdup(t);
-       fclose(fp);
+               if (!ret)
+               {
+                   /* Out of memory. XXX: an error message would be nice. */
+                   return NULL;
+               }
 
-       if (!ret)
-       {
-           /* Out of memory. XXX: an error message would be nice. */
-           explicit_bzero(buf, sizeof(buf));
-           return NULL;
-       }
+               /* De-escape password. */
+               for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
+               {
+                   if (*p1 == '\\' && p1[1] != '\0')
+                       ++p1;
+                   *p2 = *p1;
+               }
+               *p2 = '\0';
 
-       /* De-escape password. */
-       for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
-       {
-           if (*p1 == '\\' && p1[1] != '\0')
-               ++p1;
-           *p2 = *p1;
+               return ret;
+           }
        }
-       *p2 = '\0';
 
-       return ret;
+       /* No match, reset buffer to prepare for next line. */
+       buf.len = 0;
    }
 
    fclose(fp);
-   explicit_bzero(buf, sizeof(buf));
+   explicit_bzero(buf.data, buf.maxlen);
+   termPQExpBuffer(&buf);
    return NULL;
-
-#undef LINELEN
 }
 
 
 
 }
 else
 {
-   plan tests => 10;
+   plan tests => 13;
 }
 
 
 
    $status_string = 'success' if ($expected_res eq 0);
 
-   my $res = $node->psql('postgres', undef, extra_params => [ '-U', $role ]);
+   local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+   my $res = $node->psql('postgres', undef, extra_params => [ '-U', $role, '-w' ]);
    is($res, $expected_res,
        "authentication $status_string for method $method, role $role");
    return;
 reset_pg_hba($node, 'scram-sha-256');
 $ENV{"PGCHANNELBINDING"} = 'require';
 test_role($node, 'scram_role', 'scram-sha-256', 2);
+
+# Test .pgpass processing; but use a temp file, don't overwrite the real one!
+my $pgpassfile = "${TestLib::tmp_check}/pgpass";
+
+delete $ENV{"PGPASSWORD"};
+delete $ENV{"PGCHANNELBINDING"};
+$ENV{"PGPASSFILE"} = $pgpassfile;
+
+append_to_file($pgpassfile, qq!
+# This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file. This very long comment is just here to exercise handling of long lines in the file.
+*:*:postgres:scram_role:pass:this is not part of the password.
+!);
+chmod 0600, $pgpassfile or die;
+
+reset_pg_hba($node, 'password');
+test_role($node, 'scram_role', 'password from pgpass', 0);
+test_role($node, 'md5_role',   'password from pgpass', 2);
+
+append_to_file($pgpassfile, qq!
+*:*:*:md5_role:p\\ass
+!);
+
+test_role($node, 'md5_role',   'password from pgpass', 0);