Added a check for duplicate sections in the configuration file.
This commit is contained in:
@ -75,6 +75,8 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <pcre.h>
|
#include <pcre.h>
|
||||||
#include <dbusers.h>
|
#include <dbusers.h>
|
||||||
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||||
|
#include <pcre2.h>
|
||||||
|
|
||||||
/** According to the PCRE manual, this should be a multiple of 3 */
|
/** According to the PCRE manual, this should be a multiple of 3 */
|
||||||
#define MAXSCALE_PCRE_BUFSZ 24
|
#define MAXSCALE_PCRE_BUFSZ 24
|
||||||
@ -101,6 +103,7 @@ int config_get_ifaddr(unsigned char *output);
|
|||||||
int config_get_release_string(char* release);
|
int config_get_release_string(char* release);
|
||||||
FEEDBACK_CONF * config_get_feedback_data();
|
FEEDBACK_CONF * config_get_feedback_data();
|
||||||
void config_add_param(CONFIG_CONTEXT*,char*,char*);
|
void config_add_param(CONFIG_CONTEXT*,char*,char*);
|
||||||
|
bool config_has_duplicate_sections(const char* config);
|
||||||
static char *config_file = NULL;
|
static char *config_file = NULL;
|
||||||
static GATEWAY_CONF gateway;
|
static GATEWAY_CONF gateway;
|
||||||
static FEEDBACK_CONF feedback;
|
static FEEDBACK_CONF feedback;
|
||||||
@ -274,6 +277,10 @@ config_load(char *file)
|
|||||||
CONFIG_CONTEXT config;
|
CONFIG_CONTEXT config;
|
||||||
int rval, ini_rval;
|
int rval, ini_rval;
|
||||||
|
|
||||||
|
if (config_has_duplicate_sections(file))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
MYSQL *conn;
|
MYSQL *conn;
|
||||||
conn = mysql_init(NULL);
|
conn = mysql_init(NULL);
|
||||||
if (conn) {
|
if (conn) {
|
||||||
@ -356,6 +363,11 @@ int rval;
|
|||||||
if (!config_file)
|
if (!config_file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (config_has_duplicate_sections(config_file))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (gateway.version_string)
|
if (gateway.version_string)
|
||||||
free(gateway.version_string);
|
free(gateway.version_string);
|
||||||
|
|
||||||
@ -2629,3 +2641,78 @@ GATEWAY_CONF* config_get_global_options()
|
|||||||
{
|
{
|
||||||
return &gateway;
|
return &gateway;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if sections are defined multiple times in the configuration file.
|
||||||
|
* @param config Path to the configuration file
|
||||||
|
* @return True if duplicate sections were found or an error occurred
|
||||||
|
*/
|
||||||
|
bool config_has_duplicate_sections(const char* config)
|
||||||
|
{
|
||||||
|
bool rval = false;
|
||||||
|
const int table_size = 10;
|
||||||
|
int errcode;
|
||||||
|
PCRE2_SIZE erroffset;
|
||||||
|
HASHTABLE *hash = hashtable_alloc(table_size, simple_str_hash, strcmp);
|
||||||
|
pcre2_code *re = pcre2_compile((PCRE2_SPTR) "^\\s*\\[(.+)\\]\\s*$", PCRE2_ZERO_TERMINATED,
|
||||||
|
0, &errcode, &erroffset, NULL);
|
||||||
|
pcre2_match_data *mdata;
|
||||||
|
int size = 1024;
|
||||||
|
char *buffer = malloc(size * sizeof(char));
|
||||||
|
|
||||||
|
if (buffer && hash && re &&
|
||||||
|
(mdata = pcre2_match_data_create_from_pattern(re, NULL)))
|
||||||
|
{
|
||||||
|
hashtable_memory_fns(hash, (HASHMEMORYFN) strdup, NULL,
|
||||||
|
(HASHMEMORYFN) free, NULL);
|
||||||
|
FILE* file = fopen(config, "r");
|
||||||
|
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
while (maxscale_getline(&buffer, &size, file) > 0)
|
||||||
|
{
|
||||||
|
if (pcre2_match(re, (PCRE2_SPTR) buffer,
|
||||||
|
PCRE2_ZERO_TERMINATED, 0, 0,
|
||||||
|
mdata, NULL) > 0)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Neither of the PCRE2 calls will fail since we know the pattern
|
||||||
|
* beforehand and we allocate enough memory from the stack
|
||||||
|
*/
|
||||||
|
PCRE2_SIZE len;
|
||||||
|
pcre2_substring_length_bynumber(mdata, 1, &len);
|
||||||
|
len += 1; /** one for the null terminator */
|
||||||
|
PCRE2_UCHAR section[len];
|
||||||
|
pcre2_substring_copy_bynumber(mdata, 1, section, &len);
|
||||||
|
|
||||||
|
if (hashtable_add(hash, section, "") == 0)
|
||||||
|
{
|
||||||
|
skygw_log_write(LE, "Error: Duplicate section found: %s",
|
||||||
|
section);
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char errbuf[STRERROR_BUFLEN];
|
||||||
|
skygw_log_write(LE, "Error: Failed to open file '%s': %s", config,
|
||||||
|
strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skygw_log_write(LE, "Error: Failed to allocate enough memory when checking"
|
||||||
|
" for duplicate sections in configuration file.");
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashtable_free(hash);
|
||||||
|
pcre2_code_free(re);
|
||||||
|
pcre2_match_data_free(mdata);
|
||||||
|
free(buffer);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
@ -2266,3 +2266,61 @@ int simple_str_hash(char* key)
|
|||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read from a FILE pointer until a newline character or the end of the file is found.
|
||||||
|
* The provided buffer will be reallocated if it is too small to store the whole
|
||||||
|
* line. The size after the reallocation will be stored in @c size. The read line
|
||||||
|
* will be stored in @c dest and it will always be null terminated. The newline
|
||||||
|
* character will not be copied into the buffer.
|
||||||
|
* @param dest Pointer to a buffer of at least @c size bytes
|
||||||
|
* @param size Size of the buffer
|
||||||
|
* @param file A valid file stream
|
||||||
|
* @return When a complete line was successfully read the function returns 1. If
|
||||||
|
* the end of the file was reached before any characters were read the return value
|
||||||
|
* will be 0. If the provided buffer could not be reallocated to store the complete
|
||||||
|
* line the original size will be retained, everything read up to this point
|
||||||
|
* will be stored in it as a null terminated string and -1 will be returned.
|
||||||
|
*/
|
||||||
|
int maxscale_getline(char** dest, int* size, FILE* file)
|
||||||
|
{
|
||||||
|
char* destptr = *dest;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
if (feof(file))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (*size <= offset)
|
||||||
|
{
|
||||||
|
char* tmp = (char*) realloc(destptr, *size * 2);
|
||||||
|
if (tmp)
|
||||||
|
{
|
||||||
|
destptr = tmp;
|
||||||
|
*size *= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skygw_log_write(LE, "Error: Failed to reallocate memory from %d"
|
||||||
|
" bytes to %d bytes when reading from file.",
|
||||||
|
*size, *size * 2);
|
||||||
|
destptr[offset - 1] = '\0';
|
||||||
|
*dest = destptr;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((destptr[offset] = fgetc(file)) == '\n' || feof(file))
|
||||||
|
{
|
||||||
|
destptr[offset] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = destptr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -281,7 +281,7 @@ char* replace_quoted(const char* str);
|
|||||||
bool is_valid_posix_path(char* path);
|
bool is_valid_posix_path(char* path);
|
||||||
bool strip_escape_chars(char*);
|
bool strip_escape_chars(char*);
|
||||||
int simple_str_hash(char* key);
|
int simple_str_hash(char* key);
|
||||||
|
int maxscale_getline(char** dest, int* size, FILE* file);
|
||||||
|
|
||||||
EXTERN_C_BLOCK_END
|
EXTERN_C_BLOCK_END
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user