pgpool2.git / summary / log / commit / refs

commit    b0c1dbbb98bccee1c5c2e77dcdbe7a5cee6079bb
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Sun Jan 11 01:20:22 2015 +0000

    Tighten up checking for app_name_redirect_preference_list and database_redirect_preference_list.
    
    Before empty application name or database name and invalid DB node
    number (like "foo1bar") were silently accepted. Now they are strictly
    checked and let raise fatal error when starting up. Problem reported
    in [pgpool-general-jp: 1337].


src/config/pool_config.c | 99 ++++++++++++++++++++++++++++++++++++++---------- src/config/pool_config.l | 67 ++++++++++++++++++++++++++++++-- src/utils/regex_array.c | 5 +-- 3 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/config/pool_config.c b/src/config/pool_config.c index c942c7b2e..4ae3a0dfa 100644 --- a/src/config/pool_config.c +++ b/src/config/pool_config.c @@ -499,7 +499,7 @@ char *yytext; * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2014 PgPool Global Development Group + * Copyright (c) 2003-2015 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -553,8 +553,9 @@ typedef enum { static char *extract_string(char *value, POOL_TOKEN token); static char **extract_string_tokens(char *str, char *delim, int *n); static void clear_host_entry(int slot); +static bool check_redirect_node_spec(char *node_spec); -#line 558 "config/pool_config.c" +#line 559 "config/pool_config.c" #define INITIAL 0 @@ -739,10 +740,10 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 89 "pool_config.l" +#line 90 "pool_config.l" -#line 746 "config/pool_config.c" +#line 747 "config/pool_config.c" if ( !(yy_init) ) { @@ -824,12 +825,12 @@ do_action: /* This label is used only to access EOF actions. */ case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 91 "pool_config.l" +#line 92 "pool_config.l" Lineno++; return POOL_EOL; YY_BREAK case 2: YY_RULE_SETUP -#line 92 "pool_config.l" +#line 93 "pool_config.l" /* eat whitespace */ YY_BREAK case 3: @@ -837,50 +838,50 @@ case 3: (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP -#line 93 "pool_config.l" +#line 94 "pool_config.l" /* eat comment */ YY_BREAK case 4: YY_RULE_SETUP -#line 95 "pool_config.l" +#line 96 "pool_config.l" return POOL_KEY; YY_BREAK case 5: YY_RULE_SETUP -#line 96 "pool_config.l" +#line 97 "pool_config.l" return POOL_STRING; YY_BREAK case 6: YY_RULE_SETUP -#line 97 "pool_config.l" +#line 98 "pool_config.l" return POOL_UNQUOTED_STRING; YY_BREAK case 7: YY_RULE_SETUP -#line 98 "pool_config.l" +#line 99 "pool_config.l" return POOL_INTEGER; YY_BREAK case 8: YY_RULE_SETUP -#line 99 "pool_config.l" +#line 100 "pool_config.l" return POOL_REAL; YY_BREAK case 9: YY_RULE_SETUP -#line 100 "pool_config.l" +#line 101 "pool_config.l" return POOL_EQUALS; YY_BREAK case 10: YY_RULE_SETUP -#line 102 "pool_config.l" +#line 103 "pool_config.l" return POOL_PARSE_ERROR; YY_BREAK case 11: YY_RULE_SETUP -#line 104 "pool_config.l" +#line 105 "pool_config.l" ECHO; YY_BREAK -#line 884 "config/pool_config.c" +#line 885 "config/pool_config.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1838,7 +1839,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 104 "pool_config.l" +#line 105 "pool_config.l" @@ -5039,7 +5040,17 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) for (i=0;i<lrtokens->pos;i++) { - if (add_regex_array(pool_config->redirect_dbnames, lrtokens->token[i].left_token)) + if (!check_redirect_node_spec(lrtokens->token[i].right_token)) + { + fclose(fd); + ereport(error_level, + (errmsg("invalid configuration for key \"%s\"",key), + errdetail("wrong redirect db node spec: \"%s\"", lrtokens->token[i].right_token))); + return(-1); + } + + if (*(lrtokens->token[i].left_token) == '\0' || + add_regex_array(pool_config->redirect_dbnames, lrtokens->token[i].left_token)) { fclose(fd); ereport(error_level, @@ -5079,12 +5090,23 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) for (i=0;i<lrtokens->pos;i++) { - if (add_regex_array(pool_config->redirect_app_names, lrtokens->token[i].left_token)) + if (!check_redirect_node_spec(lrtokens->token[i].right_token)) { fclose(fd); ereport(error_level, (errmsg("invalid configuration for key \"%s\"",key), - errdetail("wrong redirect dbname regular expression: \"%s\"", lrtokens->token[i].left_token))); + errdetail("wrong redirect db node spec: \"%s\"", lrtokens->token[i].right_token))); + return(-1); + } + + + if (*(lrtokens->token[i].left_token) == '\0' || + add_regex_array(pool_config->redirect_app_names, lrtokens->token[i].left_token)) + { + fclose(fd); + ereport(error_level, + (errmsg("invalid configuration for key \"%s\"",key), + errdetail("wrong redirect app name regular expression: \"%s\"", lrtokens->token[i].left_token))); return(-1); } } @@ -5486,3 +5508,40 @@ char *pool_flag_to_str(unsigned short flag) return buf; } +/* + * Check DB node spec. node spec should be either "primary", "standby" or + * numeric DB node id. +*/ +bool check_redirect_node_spec(char *node_spec) +{ + int len = strlen(node_spec); + int i; + long val; + + if (len <= 0) + return false; + + if (strcasecmp("primary", node_spec) == 0) + { + return true; + } + + if (strcasecmp("standby", node_spec) == 0) + { + return true; + } + + for (i=0;i<len;i++) + { + if (!isdigit((int)node_spec[i])) + return false; + } + + val = atol(node_spec); + + if (val >=0 && val < MAX_NUM_BACKENDS) + return true; + + return false; +} + diff --git a/src/config/pool_config.l b/src/config/pool_config.l index 7d63cbeda..06634e41a 100644 --- a/src/config/pool_config.l +++ b/src/config/pool_config.l @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2014 PgPool Global Development Group + * Copyright (c) 2003-2015 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -61,6 +61,7 @@ typedef enum { static char *extract_string(char *value, POOL_TOKEN token); static char **extract_string_tokens(char *str, char *delim, int *n); static void clear_host_entry(int slot); +static bool check_redirect_node_spec(char *node_spec); %} @@ -3300,7 +3301,17 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) for (i=0;i<lrtokens->pos;i++) { - if (add_regex_array(pool_config->redirect_dbnames, lrtokens->token[i].left_token)) + if (!check_redirect_node_spec(lrtokens->token[i].right_token)) + { + fclose(fd); + ereport(error_level, + (errmsg("invalid configuration for key \"%s\"",key), + errdetail("wrong redirect db node spec: \"%s\"", lrtokens->token[i].right_token))); + return(-1); + } + + if (*(lrtokens->token[i].left_token) == '\0' || + add_regex_array(pool_config->redirect_dbnames, lrtokens->token[i].left_token)) { fclose(fd); ereport(error_level, @@ -3340,12 +3351,23 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context) for (i=0;i<lrtokens->pos;i++) { - if (add_regex_array(pool_config->redirect_app_names, lrtokens->token[i].left_token)) + if (!check_redirect_node_spec(lrtokens->token[i].right_token)) { fclose(fd); ereport(error_level, (errmsg("invalid configuration for key \"%s\"",key), - errdetail("wrong redirect dbname regular expression: \"%s\"", lrtokens->token[i].left_token))); + errdetail("wrong redirect db node spec: \"%s\"", lrtokens->token[i].right_token))); + return(-1); + } + + + if (*(lrtokens->token[i].left_token) == '\0' || + add_regex_array(pool_config->redirect_app_names, lrtokens->token[i].left_token)) + { + fclose(fd); + ereport(error_level, + (errmsg("invalid configuration for key \"%s\"",key), + errdetail("wrong redirect app name regular expression: \"%s\"", lrtokens->token[i].left_token))); return(-1); } } @@ -3746,3 +3768,40 @@ char *pool_flag_to_str(unsigned short flag) snprintf(buf, sizeof(buf), "DISALLOW_TO_FAILOVER"); return buf; } + +/* + * Check DB node spec. node spec should be either "primary", "standby" or + * numeric DB node id. +*/ +bool check_redirect_node_spec(char *node_spec) +{ + int len = strlen(node_spec); + int i; + long val; + + if (len <= 0) + return false; + + if (strcasecmp("primary", node_spec) == 0) + { + return true; + } + + if (strcasecmp("standby", node_spec) == 0) + { + return true; + } + + for (i=0;i<len;i++) + { + if (!isdigit((int)node_spec[i])) + return false; + } + + val = atol(node_spec); + + if (val >=0 && val < MAX_NUM_BACKENDS) + return true; + + return false; +} diff --git a/src/utils/regex_array.c b/src/utils/regex_array.c index 2d96b6171..bbb4bc1a9 100644 --- a/src/utils/regex_array.c +++ b/src/utils/regex_array.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2014 PgPool Global Development Group + * Copyright (c) 2003-2015 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -95,13 +95,12 @@ int add_regex_array(RegArray *ar, char *pattern) strncpy(pat, pattern, len + 1); } - if (len > 0 && pattern[len - 1] != '$') + if (len == 0 || (len > 0 && pattern[len - 1] != '$')) { strncat(pat, "$", 2); } /* Compile our regex */ - regex = palloc(sizeof(regex_t)); if (regcomp(regex, pat, regex_flags) != 0) { [parent: 2593d63ada1d]