Remove arbitrary line length limit for libpq service files.

Use a StringInfo instead of a fixed-size buffer in parseServiceInfo().
While we've not heard complaints about the existing 255-byte limit,
it certainly seems possible that complex cases could run afoul of it.

Daniel Gustafsson

Discussion: https://postgr.es/m/48A4FA71-524E-41B9-953A-FD04EF36E2E7@yesql.se
This commit is contained in:
Tom Lane 2020-09-22 15:59:23 -04:00
parent 931487018c
commit c0cb87fbb6
1 changed files with 31 additions and 37 deletions

View File

@ -28,6 +28,7 @@
#include "fe-auth.h" #include "fe-auth.h"
#include "libpq-fe.h" #include "libpq-fe.h"
#include "libpq-int.h" #include "libpq-int.h"
#include "lib/stringinfo.h"
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"
#include "pg_config_paths.h" #include "pg_config_paths.h"
#include "port/pg_bswap.h" #include "port/pg_bswap.h"
@ -5011,8 +5012,6 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
#endif /* USE_LDAP */ #endif /* USE_LDAP */
#define MAXBUFSIZE 256
/* /*
* parseServiceInfo: if a service name has been given, look it up and absorb * parseServiceInfo: if a service name has been given, look it up and absorb
* connection options from it into *options. * connection options from it into *options.
@ -5099,11 +5098,14 @@ parseServiceFile(const char *serviceFile,
PQExpBuffer errorMessage, PQExpBuffer errorMessage,
bool *group_found) bool *group_found)
{ {
int linenr = 0, int result = 0,
linenr = 0,
i; i;
FILE *f; FILE *f;
char buf[MAXBUFSIZE], char *line;
*line; StringInfoData linebuf;
*group_found = false;
f = fopen(serviceFile, "r"); f = fopen(serviceFile, "r");
if (f == NULL) if (f == NULL)
@ -5113,26 +5115,18 @@ parseServiceFile(const char *serviceFile,
return 1; return 1;
} }
while ((line = fgets(buf, sizeof(buf), f)) != NULL) initStringInfo(&linebuf);
{
int len;
while (pg_get_line_buf(f, &linebuf))
{
linenr++; linenr++;
if (strlen(line) >= sizeof(buf) - 1)
{
fclose(f);
printfPQExpBuffer(errorMessage,
libpq_gettext("line %d too long in service file \"%s\"\n"),
linenr,
serviceFile);
return 2;
}
/* ignore whitespace at end of line, especially the newline */ /* ignore whitespace at end of line, especially the newline */
len = strlen(line); while (linebuf.len > 0 &&
while (len > 0 && isspace((unsigned char) line[len - 1])) isspace((unsigned char) linebuf.data[linebuf.len - 1]))
line[--len] = '\0'; linebuf.data[--linebuf.len] = '\0';
line = linebuf.data;
/* ignore leading whitespace too */ /* ignore leading whitespace too */
while (*line && isspace((unsigned char) line[0])) while (*line && isspace((unsigned char) line[0]))
@ -5147,9 +5141,8 @@ parseServiceFile(const char *serviceFile,
{ {
if (*group_found) if (*group_found)
{ {
/* group info already read */ /* end of desired group reached; return success */
fclose(f); goto exit;
return 0;
} }
if (strncmp(line + 1, service, strlen(service)) == 0 && if (strncmp(line + 1, service, strlen(service)) == 0 &&
@ -5178,12 +5171,11 @@ parseServiceFile(const char *serviceFile,
switch (rc) switch (rc)
{ {
case 0: case 0:
fclose(f); goto exit;
return 0;
case 1: case 1:
case 3: case 3:
fclose(f); result = 3;
return 3; goto exit;
case 2: case 2:
continue; continue;
} }
@ -5198,8 +5190,8 @@ parseServiceFile(const char *serviceFile,
libpq_gettext("syntax error in service file \"%s\", line %d\n"), libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile, serviceFile,
linenr); linenr);
fclose(f); result = 3;
return 3; goto exit;
} }
*val++ = '\0'; *val++ = '\0';
@ -5209,8 +5201,8 @@ parseServiceFile(const char *serviceFile,
libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"), libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
serviceFile, serviceFile,
linenr); linenr);
fclose(f); result = 3;
return 3; goto exit;
} }
/* /*
@ -5228,8 +5220,8 @@ parseServiceFile(const char *serviceFile,
{ {
printfPQExpBuffer(errorMessage, printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n")); libpq_gettext("out of memory\n"));
fclose(f); result = 3;
return 3; goto exit;
} }
found_keyword = true; found_keyword = true;
break; break;
@ -5242,16 +5234,18 @@ parseServiceFile(const char *serviceFile,
libpq_gettext("syntax error in service file \"%s\", line %d\n"), libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile, serviceFile,
linenr); linenr);
fclose(f); result = 3;
return 3; goto exit;
} }
} }
} }
} }
exit:
fclose(f); fclose(f);
pfree(linebuf.data);
return 0; return result;
} }