diff --git a/configfile-scan.l b/configfile-scan.l index 59127b0a..1c029aed 100644 --- a/configfile-scan.l +++ b/configfile-scan.l @@ -40,11 +40,11 @@ static sigjmp_buf *CONF_flex_fatal_jmp; static char *CONF_scanstr(const char *s); static int CONF_flex_fatal(const char *msg); -static bool ProcessConfigFile(const char *base_dir, const char *config_file, const char *calling_file, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); +static bool ProcessConfigFile(const char *base_dir, const char *config_file, const char *calling_file, bool strict, int depth, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); -static bool ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); +static bool ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, int depth, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); -static bool ProcessConfigDirectory(const char *base_dir, const char *includedir, const char *calling_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); +static bool ProcessConfigDirectory(const char *base_dir, const char *includedir, const char *calling_file, int depth, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); static char *AbsoluteConfigLocation(const char *base_dir, const char *location, const char *calling_file); @@ -102,7 +102,7 @@ STRING \'([^'\\\n]|\\.|\'\')*\' extern bool ProcessRepmgrConfigFile(const char *config_file, const char *base_dir, ItemList *error_list, ItemList *warning_list) { - return ProcessConfigFile(base_dir, config_file, NULL, true, NULL, error_list, warning_list); + return ProcessConfigFile(base_dir, config_file, NULL, true, 0, NULL, error_list, warning_list); } @@ -111,11 +111,11 @@ ProcessPostgresConfigFile(const char *config_file, const char *base_dir, KeyValu { //printf("ProcessPostgresConfigFile(): base: %s file: %s\n", base_dir, config_file); - return ProcessConfigFile(base_dir, config_file, NULL, true, contents, error_list, warning_list); + return ProcessConfigFile(base_dir, config_file, NULL, true, 0, contents, error_list, warning_list); } static bool -ProcessConfigFile(const char *base_dir, const char *config_file, const char *calling_file, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) +ProcessConfigFile(const char *base_dir, const char *config_file, const char *calling_file, bool strict, int depth, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) { char *abs_path; bool success = true; @@ -130,6 +130,19 @@ ProcessConfigFile(const char *base_dir, const char *config_file, const char *cal return false; } + /* + * Reject too-deep include nesting depth. This is just a safety check to + * avoid dumping core due to stack overflow if an include file loops back + * to itself. The maximum nesting depth is pretty arbitrary. + */ + if (depth > 10) + { + item_list_append_format(error_list, + _("could not open configuration file \"%s\": maximum nesting depth exceeded"), + config_file); + return false; + } + abs_path = AbsoluteConfigLocation(base_dir, config_file, calling_file); /* Reject direct recursion */ @@ -162,7 +175,7 @@ ProcessConfigFile(const char *base_dir, const char *config_file, const char *cal } else { - success = ProcessConfigFp(fp, abs_path, calling_file, base_dir, contents, error_list, warning_list); + success = ProcessConfigFp(fp, abs_path, calling_file, depth + 1, base_dir, contents, error_list, warning_list); } free(abs_path); @@ -171,7 +184,7 @@ ProcessConfigFile(const char *base_dir, const char *config_file, const char *cal } static bool -ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) +ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, int depth, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) { volatile bool OK = true; volatile YY_BUFFER_STATE lex_buffer = NULL; @@ -256,7 +269,7 @@ ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, con * processed immediately. */ if (!ProcessConfigDirectory(base_dir, opt_value, config_file, - contents, + depth + 1, contents, error_list, warning_list)) OK = false; yy_switch_to_buffer(lex_buffer); @@ -266,7 +279,7 @@ ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, con else if (base_dir != NULL && strcasecmp(opt_name, "include_if_exists") == 0) { if (!ProcessConfigFile(base_dir, opt_value, config_file, - false, contents, + false, depth + 1, contents, error_list, warning_list)) OK = false; @@ -277,7 +290,7 @@ ProcessConfigFp(FILE *fp, const char *config_file, const char *calling_file, con else if (base_dir != NULL && strcasecmp(opt_name, "include") == 0) { if (!ProcessConfigFile(base_dir, opt_value, config_file, - true, contents, + true, depth + 1, contents, error_list, warning_list)) OK = false; @@ -370,7 +383,7 @@ cleanup: * See ProcessConfigFp for further details. */ static bool -ProcessConfigDirectory(const char *base_dir, const char *includedir, const char *calling_file, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) +ProcessConfigDirectory(const char *base_dir, const char *includedir, const char *calling_file, int depth, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) { char *directory; DIR *d; @@ -471,7 +484,7 @@ ProcessConfigDirectory(const char *base_dir, const char *includedir, const char for (i = 0; i < num_filenames; i++) { if (!ProcessConfigFile(base_dir, filenames[i], calling_file, - true, contents, + true, depth, contents, error_list, warning_list)) { status = false;