Refactor more logic for compilation of regular expressions in hba.c
authorMichael Paquier <michael@paquier.xyz>
Fri, 21 Oct 2022 00:55:56 +0000 (09:55 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 21 Oct 2022 00:55:56 +0000 (09:55 +0900)
It happens that the parts of hba.conf that are planned to be extended
to support regular expressions would finish by using the same error
message as the one used currently for pg_ident.conf when a regular
expression cannot be compiled, as long as the routine centralizing the
logic, regcomp_auth_token(), knows from which file the regexp comes from
and its line location in the so-said file.

This change makes the follow-up patches slightly simpler, and the logic
remains the same.  I suspect that this makes the proposal to add support
for file inclusions in pg_ident.conf and pg_hba.conf slightly simpler,
as well.

Extracted from a larger patch by the same author.  This is similar to
the refactoring done in fc579e1.

Author: Bertrand Drouvot
Discussion: https://postgr.es/m/fff0d7c1-8ad4-76a1-9db3-0ab6ec338bf7@amazon.com

src/backend/libpq/hba.c

index 947a1edcefdb590312f4e59108463c1b42b6d9a2..f3539a79299724d5463d85e9beb0a6cad9227a83 100644 (file)
@@ -119,7 +119,8 @@ static List *tokenize_inc_file(List *tokens, const char *outer_filename,
                               const char *inc_filename, int elevel, char **err_msg);
 static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
                               int elevel, char **err_msg);
-static int regcomp_auth_token(AuthToken *token);
+static int regcomp_auth_token(AuthToken *token, char *filename, int line_num,
+                              char **err_msg, int elevel);
 static int regexec_auth_token(const char *match, AuthToken *token,
                               size_t nmatch, regmatch_t pmatch[]);
 
@@ -305,10 +306,12 @@ copy_auth_token(AuthToken *in)
 
 /*
  * Compile the regular expression and store it in the AuthToken given in
- * input.  Returns the result of pg_regcomp().
+ * input.  Returns the result of pg_regcomp().  On error, the details are
+ * stored in "err_msg".
  */
 static int
-regcomp_auth_token(AuthToken *token)
+regcomp_auth_token(AuthToken *token, char *filename, int line_num,
+                  char **err_msg, int elevel)
 {
    pg_wchar   *wstr;
    int         wlen;
@@ -326,6 +329,22 @@ regcomp_auth_token(AuthToken *token)
 
    rc = pg_regcomp(token->regex, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
 
+   if (rc)
+   {
+       char        errstr[100];
+
+       pg_regerror(rc, token->regex, errstr, sizeof(errstr));
+       ereport(elevel,
+               (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
+                errmsg("invalid regular expression \"%s\": %s",
+                       token->string + 1, errstr),
+                errcontext("line %d of configuration file \"%s\"",
+                           line_num, filename)));
+
+       *err_msg = psprintf("invalid regular expression \"%s\": %s",
+                           token->string + 1, errstr);
+   }
+
    pfree(wstr);
    return rc;
 }
@@ -2374,7 +2393,6 @@ parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
    List       *tokens;
    AuthToken  *token;
    IdentLine  *parsedline;
-   int         rc;
 
    Assert(tok_line->fields != NIL);
    field = list_head(tok_line->fields);
@@ -2410,22 +2428,10 @@ parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
     * Now that the field validation is done, compile a regex from the user
     * token, if necessary.
     */
-   rc = regcomp_auth_token(parsedline->token);
-   if (rc)
+   if (regcomp_auth_token(parsedline->token, IdentFileName, line_num,
+                          err_msg, elevel))
    {
-       char        errstr[100];
-
-       pg_regerror(rc, parsedline->token->regex, errstr, sizeof(errstr));
-       ereport(elevel,
-               (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
-                errmsg("invalid regular expression \"%s\": %s",
-                       parsedline->token->string + 1, errstr),
-                errcontext("line %d of configuration file \"%s\"",
-                           line_num, IdentFileName)));
-
-       *err_msg = psprintf("invalid regular expression \"%s\": %s",
-                           parsedline->token->string + 1, errstr);
-
+       /* err_msg includes the error to report */
        return NULL;
    }