Problem
The bash completion script generated by --bpaf-complete-style-bash produces shell parse errors when the user's partial input contains unclosed quotes, backticks, or other shell-special characters.
For example, with a program that takes a -c flag accepting a string argument:
$ myprogram -c "bas<TAB>
bash: eval: line 5: unexpected EOF while looking for matching '"'
The same issue affects zsh:
% myprogram -c "<TAB>
(eval):1: unmatched "
Root Cause
The generated completion function in complete_run.rs (dump_bash_completer) constructs a command string via interpolation and passes it to eval:
_bpaf_dynamic_completion()
{
line="$1 --bpaf-complete-rev=8 ${COMP_WORDS[@]:1}"
if [[ ${COMP_WORDS[-1]} == "" ]]; then
line="${line} \"\""
fi
source <( eval ${line})
}
The ${COMP_WORDS[@]:1} expansion is interpolated into a flat string assigned to line, then eval ${line} re-parses that string. Any shell metacharacters in user input (unclosed ", ', `, $(), etc.) are interpreted by eval rather than being passed as literal arguments.
Context: Why eval Was Introduced
I understand that eval was added intentionally in a03ca9f to fix #315. The previous version used direct array invocation:
source <( "$1" --bpaf-complete-rev=8 "${COMP_WORDS[@]:1}" )
This broke when the program was invoked via a path containing ~ or environment variables (e.g. ~/src/myapp/target/debug/myprogram), because COMP_WORDS[0] stores the literal ~/src/... and process substitution <( ... ) doesn't perform tilde expansion.
So the eval correctly fixes the tilde/env-var expansion issue from #315 but introduces this metacharacter problem.
Possible Approach
A fix would need to preserve the tilde/env-var expansion for the program name while keeping user arguments safe. One approach: eval only the program path, then use array-based passing for everything else:
_bpaf_dynamic_completion()
{
local _prog
eval _prog="$1"
local -a _args=("$_prog" "--bpaf-complete-rev=8" "${COMP_WORDS[@]:1}")
if [[ ${COMP_WORDS[-1]} == "" ]]; then
_args+=("")
fi
source <( "${_args[@]}" )
}
This expands ~ and $VARS in the program path (preserving the #315 fix) while passing the remaining COMP_WORDS as discrete array elements, so special characters in user input are never re-interpreted.
I haven't tested this against all the edge cases you'd know better than me, so treat this as a starting point rather than a proven fix.
Versions
Observed on bpaf 0.9.x (the dump_bash_completer function in src/complete_run.rs).
Problem
The bash completion script generated by
--bpaf-complete-style-bashproduces shell parse errors when the user's partial input contains unclosed quotes, backticks, or other shell-special characters.For example, with a program that takes a
-cflag accepting a string argument:The same issue affects zsh:
Root Cause
The generated completion function in
complete_run.rs(dump_bash_completer) constructs a command string via interpolation and passes it toeval:The
${COMP_WORDS[@]:1}expansion is interpolated into a flat string assigned toline, theneval ${line}re-parses that string. Any shell metacharacters in user input (unclosed",',`,$(), etc.) are interpreted byevalrather than being passed as literal arguments.Context: Why eval Was Introduced
I understand that
evalwas added intentionally in a03ca9f to fix #315. The previous version used direct array invocation:This broke when the program was invoked via a path containing
~or environment variables (e.g.~/src/myapp/target/debug/myprogram), becauseCOMP_WORDS[0]stores the literal~/src/...and process substitution<( ... )doesn't perform tilde expansion.So the
evalcorrectly fixes the tilde/env-var expansion issue from #315 but introduces this metacharacter problem.Possible Approach
A fix would need to preserve the tilde/env-var expansion for the program name while keeping user arguments safe. One approach:
evalonly the program path, then use array-based passing for everything else:This expands
~and$VARSin the program path (preserving the #315 fix) while passing the remaining COMP_WORDS as discrete array elements, so special characters in user input are never re-interpreted.I haven't tested this against all the edge cases you'd know better than me, so treat this as a starting point rather than a proven fix.
Versions
Observed on bpaf 0.9.x (the
dump_bash_completerfunction insrc/complete_run.rs).