1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-28 11:44:57 +03:00

Fix pg_isblank()

There was a pg_isblank() function that claimed to be a replacement for
the standard isblank() function, which was thought to be "not very
portable yet".  We can now assume that it's portable (it's in C99).

But pg_isblank() actually diverged from the standard isblank() by also
accepting '\r', while the standard one only accepts space and tab.
This was added to support parsing pg_hba.conf under Windows.  But the
hba parsing code now works completely differently and already handles
line endings before we get to pg_isblank().  The other user of
pg_isblank() is for ident protocol message parsing, which also handles
'\r' separately.  So this behavior is now obsolete and confusing.

To improve clarity, I separated those concerns.  The ident parsing now
gets its own function that hardcodes the whitespace characters
mentioned by the relevant RFC.  pg_isblank() is now static in hba.c
and is a wrapper around the standard isblank(), with some extra logic
to ensure robust treatment of non-ASCII characters.

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/170308e6-a7a3-4484-87b2-f960bb564afa%40eisentraut.org
This commit is contained in:
Peter Eisentraut
2025-11-28 07:53:12 +01:00
parent e68b6adad9
commit 8b3e2c622a
3 changed files with 16 additions and 11 deletions

View File

@@ -1580,6 +1580,15 @@ pg_SSPI_make_upn(char *accountname,
*----------------------------------------------------------------
*/
/*
* Per RFC 1413, space and tab are whitespace in ident messages.
*/
static bool
is_ident_whitespace(const char c)
{
return c == ' ' || c == '\t';
}
/*
* Parse the string "*ident_response" as a response from a query to an Ident
* server. If it's a normal response indicating a user name, return true
@@ -1613,14 +1622,14 @@ interpret_ident_response(const char *ident_response,
int i; /* Index into *response_type */
cursor++; /* Go over colon */
while (pg_isblank(*cursor))
while (is_ident_whitespace(*cursor))
cursor++; /* skip blanks */
i = 0;
while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
while (*cursor != ':' && *cursor != '\r' && !is_ident_whitespace(*cursor) &&
i < (int) (sizeof(response_type) - 1))
response_type[i++] = *cursor++;
response_type[i] = '\0';
while (pg_isblank(*cursor))
while (is_ident_whitespace(*cursor))
cursor++; /* skip blanks */
if (strcmp(response_type, "USERID") != 0)
return false;
@@ -1643,7 +1652,7 @@ interpret_ident_response(const char *ident_response,
else
{
cursor++; /* Go over colon */
while (pg_isblank(*cursor))
while (is_ident_whitespace(*cursor))
cursor++; /* skip blanks */
/* Rest of line is user name. Copy it over. */
i = 0;

View File

@@ -138,14 +138,11 @@ static int regexec_auth_token(const char *match, AuthToken *token,
static void tokenize_error_callback(void *arg);
/*
* isblank() exists in the ISO C99 spec, but it's not very portable yet,
* so provide our own version.
*/
bool
static bool
pg_isblank(const char c)
{
return c == ' ' || c == '\t' || c == '\r';
/* don't accept non-ASCII data */
return (!IS_HIGHBIT_SET(c) && isblank(c));
}

View File

@@ -181,7 +181,6 @@ extern int check_usermap(const char *usermap_name,
bool case_insensitive);
extern HbaLine *parse_hba_line(TokenizedAuthLine *tok_line, int elevel);
extern IdentLine *parse_ident_line(TokenizedAuthLine *tok_line, int elevel);
extern bool pg_isblank(const char c);
extern FILE *open_auth_file(const char *filename, int elevel, int depth,
char **err_msg);
extern void free_auth_file(FILE *file, int depth);