diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2018-07-09 23:22:21 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2018-07-11 15:47:08 +0200 |
commit | 5314c513f23688462d7f7937e5ae5e0d5cd4548e (patch) | |
tree | 9a2eea692f88cf5f87534a4cdc85014d244af4c2 /tests | |
parent | 4e0add239f6516c11631a7539653bac6b6a51970 (diff) |
vty: fix use-after-free and memleaks in is_cmd_ambiguous()
vty_test: add test against ambiguous cmd causing use-after-free and memory
leaks. Add this test along with the fix, because the new test triggers the
memory use-after-free and leaks, causing build failures.
Add cmd_deopt_with_ctx() to allow passing a specific talloc ctx.
is_cmd_ambiguous(): keep all cmd_deopt() allocations until the function exits.
Add a comment explaining why. Before this, if a command matched an optional
"[arg]" with square brackets, we would keep it in local var 'matched', but we
would free the string it points to at the end of that loop iteration; upon
encountering another match, we would attempt to strcmp against the freed
'matched'. Instead of adding hard-to-read and -verify free/alloc dances to keep
the 'matched' accurately freed/non-freed/..., just keep all cmd_deopt() string
allocated until done.
Needless to say that this should have been implemented on a lower level upon
inventing optional args, but at least this is fixing a program crash.
Related: OS#33903390
Change-Id: Ia71ba742108b5ff020997bfb612ad5eb30d04fcd
Diffstat (limited to 'tests')
-rw-r--r-- | tests/vty/vty_test.c | 62 | ||||
-rw-r--r-- | tests/vty/vty_test.ok | 19 |
2 files changed, 81 insertions, 0 deletions
diff --git a/tests/vty/vty_test.c b/tests/vty/vty_test.c index a3478e1d..30efb9af 100644 --- a/tests/vty/vty_test.c +++ b/tests/vty/vty_test.c @@ -385,6 +385,42 @@ DEFUN(cfg_level3_child, cfg_level3_child_cmd, return CMD_SUCCESS; } +DEFUN(cfg_ambiguous_nr_1, cfg_ambiguous_nr_1_cmd, + "ambiguous_nr [<0-23>]", + "testing is_cmd_ambiguous()\n" + "optional number arg\n") +{ + printf("Called: 'ambiguous_nr [<0-23>]' (argc=%d)\n", argc); + return CMD_SUCCESS; +} + +DEFUN(cfg_ambiguous_nr_2, cfg_ambiguous_nr_2_cmd, + "ambiguous_nr <0-23> keyword", + "testing is_cmd_ambiguous()\n" + "optional number arg\n") +{ + printf("Called: 'ambiguous_nr <0-23> keyword'\n"); + return CMD_SUCCESS; +} + +DEFUN(cfg_ambiguous_str_1, cfg_ambiguous_str_1_cmd, + "ambiguous_str [ARG]", + "testing is_cmd_ambiguous()\n" + "optional string arg\n") +{ + printf("Called: 'ambiguous_str [ARG]' (argc=%d)\n", argc); + return CMD_SUCCESS; +} + +DEFUN(cfg_ambiguous_str_2, cfg_ambiguous_str_2_cmd, + "ambiguous_str ARG keyword", + "testing is_cmd_ambiguous()\n" + "optional string arg\n") +{ + printf("Called: 'ambiguous_str ARG keyword'\n"); + return CMD_SUCCESS; +} + void test_vty_add_cmds() { install_element(CONFIG_NODE, &cfg_level1_cmd); @@ -398,6 +434,30 @@ void test_vty_add_cmds() install_node(&level3_node, NULL); install_element(LEVEL3_NODE, &cfg_level3_child_cmd); + + install_element_ve(&cfg_ambiguous_nr_1_cmd); + install_element_ve(&cfg_ambiguous_nr_2_cmd); + install_element_ve(&cfg_ambiguous_str_1_cmd); + install_element_ve(&cfg_ambiguous_str_2_cmd); +} + +void test_is_cmd_ambiguous() +{ + struct vty *vty; + struct vty_test test; + + printf("Going to test is_cmd_ambiguous()\n"); + vty = create_test_vty(&test); + + OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr") == CMD_SUCCESS); + OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr 23") == CMD_SUCCESS); + OSMO_ASSERT(do_vty_command(vty, "ambiguous_nr 23 keyword") == CMD_SUCCESS); + + OSMO_ASSERT(do_vty_command(vty, "ambiguous_str") == CMD_SUCCESS); + OSMO_ASSERT(do_vty_command(vty, "ambiguous_str arg") == CMD_SUCCESS); + OSMO_ASSERT(do_vty_command(vty, "ambiguous_str arg keyword") == CMD_SUCCESS); + + destroy_test_vty(&test, vty); } static int go_parent_cb(struct vty *vty) @@ -465,6 +525,8 @@ int main(int argc, char **argv) test_exit_by_indent("ok_indented_root.cfg", 0); test_exit_by_indent("ok_empty_parent.cfg", 0); + test_is_cmd_ambiguous(); + /* Leak check */ OSMO_ASSERT(talloc_total_blocks(stats_ctx) == 1); diff --git a/tests/vty/vty_test.ok b/tests/vty/vty_test.ok index bd6c5d66..2f76ff91 100644 --- a/tests/vty/vty_test.ok +++ b/tests/vty/vty_test.ok @@ -286,4 +286,23 @@ called level2 node k called level3 node k called level1 child cmd k got rc=0 +Going to test is_cmd_ambiguous() +Going to execute 'ambiguous_nr' +Called: 'ambiguous_nr [<0-23>]' (argc=0) +Returned: 0, Current node: 1 '%s> ' +Going to execute 'ambiguous_nr 23' +Called: 'ambiguous_nr [<0-23>]' (argc=1) +Returned: 0, Current node: 1 '%s> ' +Going to execute 'ambiguous_nr 23 keyword' +Called: 'ambiguous_nr <0-23> keyword' +Returned: 0, Current node: 1 '%s> ' +Going to execute 'ambiguous_str' +Called: 'ambiguous_str [ARG]' (argc=0) +Returned: 0, Current node: 1 '%s> ' +Going to execute 'ambiguous_str arg' +Called: 'ambiguous_str [ARG]' (argc=1) +Returned: 0, Current node: 1 '%s> ' +Going to execute 'ambiguous_str arg keyword' +Called: 'ambiguous_str ARG keyword' +Returned: 0, Current node: 1 '%s> ' All tests passed |