mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Silently ignore recursive calls to complete -C
without parameter
In e167714899
we allowed recursive calls
to complete. However, some completions use infinite recursion in their
completions and rely on `complete` to silently stop as soon as it is
called recursively twice without parameter (thus completing the
current commandline). For example:
complete -c su -s -xa "(complete -C(commandline -ct))"
su -c <TAB>
Infinite recursion happens because (commandline -ct) is an empty list,
which would print an error message. This commmit explicitly detects
such recursive calls where `complete` has no parameter and silently
terminates. This enables above completion (like before raising the
recursion limit) while still allowing legitimate cases with limited
recursion.
Closes #6171
This commit is contained in:
parent
cf3b24cf62
commit
2d2e15b63d
2 changed files with 11 additions and 2 deletions
|
@ -336,11 +336,16 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
parser.libdata().transient_commandlines.push_back(do_complete_param);
|
||||
cleanup_t remove_transient([&] { parser.libdata().transient_commandlines.pop_back(); });
|
||||
|
||||
// Allow a limited number of recursive calls to complete (#3474).
|
||||
if (parser.libdata().builtin_complete_recursion_level >= 24) {
|
||||
if (parser.libdata().builtin_complete_current_commandline) {
|
||||
// Prevent accidental recursion (see #6171).
|
||||
} else if (parser.libdata().builtin_complete_recursion_level >= 24) {
|
||||
// Allow a limited number of recursive calls to complete (#3474).
|
||||
streams.err.append_format(L"%ls: maximum recursion depth reached\n", cmd);
|
||||
} else {
|
||||
parser.libdata().builtin_complete_recursion_level++;
|
||||
assert(!parser.libdata().builtin_complete_current_commandline);
|
||||
if (!have_do_complete_param)
|
||||
parser.libdata().builtin_complete_current_commandline = true;
|
||||
|
||||
std::vector<completion_t> comp;
|
||||
complete(do_complete_param, &comp, completion_request_t::fuzzy_match, parser.vars(),
|
||||
|
@ -379,6 +384,7 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
}
|
||||
|
||||
parser.libdata().builtin_complete_recursion_level--;
|
||||
parser.libdata().builtin_complete_current_commandline = false;
|
||||
}
|
||||
} else if (cmd_to_complete.empty() && path.empty()) {
|
||||
// No arguments specified, meaning we print the definitions of all specified completions
|
||||
|
|
|
@ -132,6 +132,9 @@ struct library_data_t {
|
|||
/// Number of recursive calls to builtin_complete().
|
||||
uint32_t builtin_complete_recursion_level{0};
|
||||
|
||||
/// Whether we called builtin_complete -C without parameter.
|
||||
bool builtin_complete_current_commandline{false};
|
||||
|
||||
/// Whether we are currently cleaning processes.
|
||||
bool is_cleaning_procs{false};
|
||||
|
||||
|
|
Loading…
Reference in a new issue