diff --git a/src/misc.c b/src/misc.c index c7174b84..25df5910 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1012,6 +1012,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) { for (i = 0; *p != '\0'; p++) { if (*p != '%') { + escape: buf[i] = *p; i++; if (i >= MAX_BUF_SIZE) { @@ -1028,6 +1029,8 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) { } switch (*p) { + case '%': + goto escape; case 'd': x = strdup(session->opts.sshdir); break; diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c index 26da536b..8acffa0c 100644 --- a/tests/unittests/torture_misc.c +++ b/tests/unittests/torture_misc.c @@ -192,6 +192,18 @@ static void torture_path_expand_known_hosts(void **state) { free(tmp); } +static void torture_path_expand_percent(void **state) { + ssh_session session = *state; + char *tmp; + + session->opts.sshdir = strdup("/home/guru/.ssh"); + + tmp = ssh_path_expand_escape(session, "%d/config%%1"); + assert_non_null(tmp); + assert_string_equal(tmp, "/home/guru/.ssh/config%1"); + free(tmp); +} + static void torture_timeout_elapsed(void **state){ struct ssh_timestamp ts; (void) state; @@ -365,6 +377,7 @@ int torture_run_tests(void) { #endif cmocka_unit_test_setup_teardown(torture_path_expand_escape, setup, teardown), cmocka_unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown), + cmocka_unit_test_setup_teardown(torture_path_expand_percent, setup, teardown), cmocka_unit_test(torture_timeout_elapsed), cmocka_unit_test(torture_timeout_update), cmocka_unit_test(torture_ssh_analyze_banner),