diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-08 00:39:16 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-08 00:39:16 +0200 |
commit | 30af5938afad076e12b8ece123cab0b8bc92a596 (patch) | |
tree | 845ac3f69f996ddc91e37cd2f07a34636cdd5bdf /shell | |
parent | 6a9b3f7acfaa7365515f1eb70427d5ddd687c162 (diff) | |
download | busybox-w32-30af5938afad076e12b8ece123cab0b8bc92a596.tar.gz busybox-w32-30af5938afad076e12b8ece123cab0b8bc92a596.tar.bz2 busybox-w32-30af5938afad076e12b8ece123cab0b8bc92a596.zip |
ash: parser: Fix handling of empty aliases
Upstream commit:
Date: Tue, 28 Apr 2020 01:15:26 +1000
parser: Fix handling of empty aliases
Dash was incorrectly handling empty aliases. When attempting to use an
empty alias with nothing else, I'm (incorrectly) prompted for more
input:
```
$ alias empty=''
$ empty
>
```
Other shells (e.g., bash, yash) correctly handle the lone, empty alias as an
empty command:
```
$ alias empty=''
$ empty
$
```
The problem here is that we incorrectly enter the loop eating TNLs
in readtoken(). This patch fixes it by setting checkkwd correctly.
function old new delta
list 351 355 +4
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 36 |
1 files changed, 15 insertions, 21 deletions
diff --git a/shell/ash.c b/shell/ash.c index 35dbb2f28..5a18ff1a1 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -11755,27 +11755,28 @@ static union node *andor(void); | |||
11755 | static union node *pipeline(void); | 11755 | static union node *pipeline(void); |
11756 | static union node *parse_command(void); | 11756 | static union node *parse_command(void); |
11757 | static void parseheredoc(void); | 11757 | static void parseheredoc(void); |
11758 | static int peektoken(void); | ||
11759 | static int readtoken(void); | 11758 | static int readtoken(void); |
11760 | 11759 | ||
11761 | static union node * | 11760 | static union node * |
11762 | list(int nlflag) | 11761 | list(int nlflag) |
11763 | { | 11762 | { |
11763 | int chknl = nlflag & 1 ? 0 : CHKNL; | ||
11764 | union node *n1, *n2, *n3; | 11764 | union node *n1, *n2, *n3; |
11765 | int tok; | 11765 | int tok; |
11766 | 11766 | ||
11767 | n1 = NULL; | 11767 | n1 = NULL; |
11768 | for (;;) { | 11768 | for (;;) { |
11769 | switch (readtoken()) { | 11769 | checkkwd = chknl | CHKKWD | CHKALIAS; |
11770 | tok = readtoken(); | ||
11771 | switch (tok) { | ||
11770 | case TNL: | 11772 | case TNL: |
11771 | if (!(nlflag & 1)) | ||
11772 | break; | ||
11773 | parseheredoc(); | 11773 | parseheredoc(); |
11774 | return n1; | 11774 | return n1; |
11775 | 11775 | ||
11776 | case TEOF: | 11776 | case TEOF: |
11777 | if (!n1 && (nlflag & 1)) | 11777 | if (!n1 && !chknl) |
11778 | n1 = NODE_EOF; | 11778 | n1 = NODE_EOF; |
11779 | out_eof: | ||
11779 | parseheredoc(); | 11780 | parseheredoc(); |
11780 | tokpushback++; | 11781 | tokpushback++; |
11781 | lasttoken = TEOF; | 11782 | lasttoken = TEOF; |
@@ -11783,8 +11784,7 @@ list(int nlflag) | |||
11783 | } | 11784 | } |
11784 | 11785 | ||
11785 | tokpushback++; | 11786 | tokpushback++; |
11786 | checkkwd = CHKNL | CHKKWD | CHKALIAS; | 11787 | if (nlflag == 2 && ((1 << tok) & tokendlist)) |
11787 | if (nlflag == 2 && ((1 << peektoken()) & tokendlist)) | ||
11788 | return n1; | 11788 | return n1; |
11789 | nlflag |= 2; | 11789 | nlflag |= 2; |
11790 | 11790 | ||
@@ -11813,15 +11813,16 @@ list(int nlflag) | |||
11813 | n1 = n3; | 11813 | n1 = n3; |
11814 | } | 11814 | } |
11815 | switch (tok) { | 11815 | switch (tok) { |
11816 | case TNL: | ||
11817 | case TEOF: | 11816 | case TEOF: |
11817 | goto out_eof; | ||
11818 | case TNL: | ||
11818 | tokpushback = 1; | 11819 | tokpushback = 1; |
11819 | /* fall through */ | 11820 | /* fall through */ |
11820 | case TBACKGND: | 11821 | case TBACKGND: |
11821 | case TSEMI: | 11822 | case TSEMI: |
11822 | break; | 11823 | break; |
11823 | default: | 11824 | default: |
11824 | if ((nlflag & 1)) | 11825 | if (!chknl) |
11825 | raise_error_unexpected_syntax(-1); | 11826 | raise_error_unexpected_syntax(-1); |
11826 | tokpushback = 1; | 11827 | tokpushback = 1; |
11827 | return n1; | 11828 | return n1; |
@@ -11995,8 +11996,9 @@ simplecmd(void) | |||
11995 | switch (t) { | 11996 | switch (t) { |
11996 | #if BASH_FUNCTION | 11997 | #if BASH_FUNCTION |
11997 | case TFUNCTION: | 11998 | case TFUNCTION: |
11998 | if (peektoken() != TWORD) | 11999 | if (readtoken() != TWORD) |
11999 | raise_error_unexpected_syntax(TWORD); | 12000 | raise_error_unexpected_syntax(TWORD); |
12001 | tokpushback = 1; | ||
12000 | function_flag = 1; | 12002 | function_flag = 1; |
12001 | break; | 12003 | break; |
12002 | #endif | 12004 | #endif |
@@ -12033,7 +12035,9 @@ simplecmd(void) | |||
12033 | #if BASH_FUNCTION | 12035 | #if BASH_FUNCTION |
12034 | if (function_flag) { | 12036 | if (function_flag) { |
12035 | checkkwd = CHKNL | CHKKWD; | 12037 | checkkwd = CHKNL | CHKKWD; |
12036 | switch (peektoken()) { | 12038 | t = readtoken(); |
12039 | tokpushback = 1; | ||
12040 | switch (t) { | ||
12037 | case TBEGIN: | 12041 | case TBEGIN: |
12038 | case TIF: | 12042 | case TIF: |
12039 | case TCASE: | 12043 | case TCASE: |
@@ -13306,16 +13310,6 @@ readtoken(void) | |||
13306 | return t; | 13310 | return t; |
13307 | } | 13311 | } |
13308 | 13312 | ||
13309 | static int | ||
13310 | peektoken(void) | ||
13311 | { | ||
13312 | int t; | ||
13313 | |||
13314 | t = readtoken(); | ||
13315 | tokpushback = 1; | ||
13316 | return t; | ||
13317 | } | ||
13318 | |||
13319 | /* | 13313 | /* |
13320 | * Read and parse a command. Returns NODE_EOF on end of file. | 13314 | * Read and parse a command. Returns NODE_EOF on end of file. |
13321 | * (NULL is a valid parse tree indicating a blank line.) | 13315 | * (NULL is a valid parse tree indicating a blank line.) |