From b993e97bb4d2110a28e14c329b16edfe4dc53de8 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 18 Nov 2010 22:43:48 +0100 Subject: [PATCH] Fix bug in config parser where 'foo=bar' did not work, but 'foo = bar' did work due to extra whitespace between tokens. --- autotest/test_tokenizer.tcc | 19 ++++++++++++++++ src/util/config_token.c | 44 ++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/autotest/test_tokenizer.tcc b/autotest/test_tokenizer.tcc index 5bd833b..a8c7f94 100644 --- a/autotest/test_tokenizer.tcc +++ b/autotest/test_tokenizer.tcc @@ -84,5 +84,24 @@ EXO_TEST(tokenizer_escape_5, { return compare("\"value1\" value\\\\2", "value1 v EXO_TEST(tokenizer_escape_6, { return compare("\"value1\" value\\\t2", "value1 value|2"); }); EXO_TEST(tokenizer_escape_7, { return compare("\"value1\" \"value\t2\"", "value1 value|2"); }); +static int test_setting(const char* str, const char* expected_key, const char* expected_value) +{ + int success = 0; + struct cfg_settings* setting = cfg_settings_split(str); + if (!setting) return expected_key == NULL; + success = (!strcmp(cfg_settings_get_key(setting), expected_key) && !strcmp(cfg_settings_get_value(setting), expected_value)); + cfg_settings_free(setting); + return success; +} + +EXO_TEST(tokenizer_settings_1, { return test_setting("foo=bar", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_2, { return test_setting("foo =bar", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_3, { return test_setting("foo= bar", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_4, { return test_setting("\tfoo=bar", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_5, { return test_setting("foo=bar\t", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_6, { return test_setting("\tfoo=bar\t", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_7, { return test_setting("\tfoo\t=\tbar\t", "foo", "bar"); }); +EXO_TEST(tokenizer_settings_8, { return test_setting("foo=", "foo", ""); }); +EXO_TEST(tokenizer_settings_9, { return test_setting("=bar", NULL, ""); }); diff --git a/src/util/config_token.c b/src/util/config_token.c index df63163..6c7373b 100644 --- a/src/util/config_token.c +++ b/src/util/config_token.c @@ -172,7 +172,7 @@ struct cfg_settings* cfg_settings_split(const char* line) || ((pos = (char*) strchr(line, '=')) == NULL) || ((s = hub_malloc_zero(sizeof(struct cfg_settings))) == NULL) || ((tok = cfg_tokenize(line)) == NULL) - || (cfg_token_count(tok) < 2) + || (cfg_token_count(tok) < 1) || (cfg_token_count(tok) > 3) || (cfg_token_count(tok) == 3 && strcmp(cfg_token_get(tok, 1), "=")) ) @@ -182,10 +182,17 @@ struct cfg_settings* cfg_settings_split(const char* line) return NULL; } - if (cfg_token_count(tok) == 2) + if (cfg_token_count(tok) == 1) { char* key = cfg_token_get_first(tok); pos = strchr(key, '='); + if (!pos) + { + cfg_tokens_free(tok); + cfg_settings_free(s); + return NULL; + } + pos[0] = 0; key = strip_white_space(key); @@ -197,7 +204,38 @@ struct cfg_settings* cfg_settings_split(const char* line) } s->key = strdup(key); - s->value = strdup(strip_white_space(cfg_token_get_next(tok))); + s->value = strdup(strip_white_space(pos+1)); + } + else if (cfg_token_count(tok) == 2) + { + char* key = cfg_token_get_first(tok); + char* val = cfg_token_get_next(tok); + + if ((pos = strchr(key, '='))) + { + pos[0] = 0; + key = strip_white_space(key); + } + else if ((pos = strchr(val, '='))) + { + val = strip_white_space(pos+1); + } + else + { + cfg_tokens_free(tok); + cfg_settings_free(s); + return NULL; + } + + if (!*key) + { + cfg_tokens_free(tok); + cfg_settings_free(s); + return NULL; + } + + s->key = strdup(key); + s->value = strdup(val); } else {