From 241973700697abb60104c656a0aacfd182eb2316 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 14 Apr 2014 23:01:57 +0100 Subject: [PATCH] Check for duplicate options in option parser --- src/tools/parser.c | 21 +++++++++++++++++++-- tests/test_parser.c | 20 ++++++++++++++++++++ tests/test_parser.h | 3 ++- tests/testsuite.c | 1 + 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/tools/parser.c b/src/tools/parser.c index 375572e0..b4403d06 100644 --- a/src/tools/parser.c +++ b/src/tools/parser.c @@ -385,14 +385,31 @@ parse_options(gchar **args, int start, GList *keys, gboolean *res) return options; } - // check each option is valid and has value, failure if not + // validate options int curr; + GList *found_keys = NULL; for (curr = start; curr < g_strv_length(args); curr+= 2) { - if ((g_list_find(keys, args[curr]) == NULL) || (args[curr+1] == NULL)) { + // check if option valid + if (g_list_find(keys, args[curr]) == NULL) { *res = FALSE; return options; } + + // check if duplicate + if (g_list_find(found_keys, args[curr]) != NULL) { + *res = FALSE; + return options; + } + + // check value given + if (args[curr+1] == NULL) { + *res = FALSE; + return options; + } + + found_keys = g_list_append(found_keys, args[curr]); } + g_list_free(found_keys); // create map options = g_hash_table_new(g_str_hash, g_str_equal); diff --git a/tests/test_parser.c b/tests/test_parser.c index 1309e8e1..6e1d4cde 100644 --- a/tests/test_parser.c +++ b/tests/test_parser.c @@ -666,5 +666,25 @@ parse_options_when_unknown_opt_sets_error(void **state) assert_null(options); assert_false(res); + options_destroy(options); +} + +void +parse_options_with_duplicated_option_sets_error(void **state) +{ + gchar *args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", "opt1", "val3", NULL }; + + GList *keys = NULL; + keys = g_list_append(keys, "opt1"); + keys = g_list_append(keys, "opt2"); + keys = g_list_append(keys, "opt3"); + + gboolean res = TRUE; + + GHashTable *options = parse_options(args, 2, keys, &res); + + assert_null(options); + assert_false(res); + options_destroy(options); } \ No newline at end of file diff --git a/tests/test_parser.h b/tests/test_parser.h index 70b94b50..51d768fe 100644 --- a/tests/test_parser.h +++ b/tests/test_parser.h @@ -46,4 +46,5 @@ void parse_options_when_opt2_no_val_sets_error(void **state); void parse_options_when_two_returns_map(void **state); void parse_options_when_opt3_no_val_sets_error(void **state); void parse_options_when_three_returns_map(void **state); -void parse_options_when_unknown_opt_sets_error(void **state); \ No newline at end of file +void parse_options_when_unknown_opt_sets_error(void **state); +void parse_options_with_duplicated_option_sets_error(void **state); diff --git a/tests/testsuite.c b/tests/testsuite.c index c6577410..05f03188 100644 --- a/tests/testsuite.c +++ b/tests/testsuite.c @@ -173,6 +173,7 @@ int main(int argc, char* argv[]) { unit_test(parse_options_when_opt3_no_val_sets_error), unit_test(parse_options_when_three_returns_map), unit_test(parse_options_when_unknown_opt_sets_error), + unit_test(parse_options_with_duplicated_option_sets_error), unit_test(empty_list_when_none_added), unit_test(contains_one_element),