Bug 14216 - lineedit: tab completion special char set seems wrong
Summary: lineedit: tab completion special char set seems wrong
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Other (show other bugs)
Version: unspecified
Hardware: All Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-17 13:54 UTC by bugdal
Modified: 2021-09-17 15:36 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description bugdal 2021-09-17 13:54:18 UTC
I investigated the is_special_char function in lineedit.c after being annoyed that ash was completing colon characters in filenames with timestamps in them as "\:" rather than ":" despite the colon not being a shell special. I found what seem to be several mistakes.

If further found that ], +, and ^ are treated as special, which seems wrong. ] and ^ have meaning inside bracket expressions where tab completion can't happen/makes no sense, but are otherwise non-special, and AFAIK + is special only inside certain ${ forms where the same applies.

Moreover, ~, \t, and \n seem to be missing from the list of specials. For ~, this might make filenames beginning with a ~ get expanded unquoted, then re-expanded as ~ expansions when the command is later evaluated. I'm not sure if \t and \n can be expanded at all, or if they're blocked at another layer, but if they can, they need escaping too.
Comment 1 Denys Vlasenko 2021-09-17 15:36:16 UTC
Fixed in git:

 static const char *is_special_char(char c)
 {
-       return strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", c);
+       // {: It's mandatory to escape { only if entire name is "{"
+       // (otherwise it's not special. Example: file named "{ "
+       // can be escaped simply as "{\ "; "{a" or "a{" need no escaping),
+       // or if shell supports brace expansion
+       // (ash doesn't, hush optionally does).
+       // (): unlike {, shell treats () specially even in contexts
+       // where they clearly are not valid (e.g. "echo )" is an error).
+       // #: needs escaping to not start a shell comment.
+       return strchr(" `'\"\\#$~?*[{()&;|<>", c);
+       // Used to also have %^=+}]: but not necessary to escape?
 }