From 0a0149cc2a50e25e4ef2f9b99a4a2102c310d79b Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 22 Sep 2020 00:55:28 +0200 Subject: [PATCH] Prevent infinite recursion when completion wraps variable assignment Closes #7344 Apply a targeted fix to the place where complete() is called to handle nested variable assignments. Sadly, reporting an error is probably not okay here, because people might legitimately use aliases like: alias vim "A=B command vim" This is all a bit ugly, and I hope to find a cleaner solution. Supporting completions on commandlines like `x=$PWD cd $x/ ` is a nice feature but it comes with some complexity. --- src/complete.cpp | 10 ++++++++-- tests/checks/wraps.fish | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/complete.cpp b/src/complete.cpp index 47f492c89..9450f06af 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1600,8 +1600,14 @@ void completer_t::perform() { ctx.parser->libdata().transient_commandlines.push_back(unaliased_cmd); cleanup_t remove_transient( [&] { ctx.parser->libdata().transient_commandlines.pop_back(); }); - vec_append(this->completions, - complete(unaliased_cmd, completion_request_t::fuzzy_match, ctx)); + // Prevent infinite recursion when the completion for x wraps "A=B x" (#7344). + // Don't report an error since this could be a legitimate alias. + static uint32_t complete_assignment_recursion_count; + if (complete_assignment_recursion_count++ < 24) { + vec_append(this->completions, + complete(unaliased_cmd, completion_request_t::fuzzy_match, ctx)); + } + complete_assignment_recursion_count--; do_file = false; } else if (!complete_param( cmd, previous_argument_unescape, current_argument_unescape, diff --git a/tests/checks/wraps.fish b/tests/checks/wraps.fish index 3424ed958..cd85051b3 100644 --- a/tests/checks/wraps.fish +++ b/tests/checks/wraps.fish @@ -26,3 +26,7 @@ complete -c testcommand2 --wraps "testcommand2 from_wraps " complete -C'testcommand2 explicit ' # CHECKERR: explicit # CHECKERR: from_wraps explicit + + +complete -c recvar --wraps 'A=B recvar' +complete -C 'recvar '