diff options
author | Ron Yorston <rmy@pobox.com> | 2020-02-25 10:06:11 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-02-25 10:06:11 +0000 |
commit | e2a5b8e5e936891142cb630d145e67882711fd13 (patch) | |
tree | 94f685ed6e14582e7d0dfd140699082315f959f4 | |
parent | 35da75bde8885d1922701a36baa61bc8b01f14d4 (diff) | |
parent | c2058ec98cf3f6722be4436cae07a386e3c7b48d (diff) | |
download | busybox-w32-e2a5b8e5e936891142cb630d145e67882711fd13.tar.gz busybox-w32-e2a5b8e5e936891142cb630d145e67882711fd13.tar.bz2 busybox-w32-e2a5b8e5e936891142cb630d145e67882711fd13.zip |
Merge branch 'busybox' into merge
-rw-r--r-- | shell/ash.c | 110 | ||||
-rw-r--r-- | shell/ash_test/ash-heredoc/heredoc_side_effects.right | 1 | ||||
-rwxr-xr-x | shell/ash_test/ash-heredoc/heredoc_side_effects.tests | 5 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/negative_arith.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/negative_arith.tests | 8 | ||||
-rw-r--r-- | shell/hush.c | 24 | ||||
-rw-r--r-- | shell/hush_test/hush-quoting/negative_arith.right | 2 | ||||
-rwxr-xr-x | shell/hush_test/hush-quoting/negative_arith.tests | 8 |
8 files changed, 101 insertions, 59 deletions
diff --git a/shell/ash.c b/shell/ash.c index 252061dae..690796740 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -1842,15 +1842,16 @@ popstackmark(struct stackmark *mark) | |||
1842 | * part of the block that has been used. | 1842 | * part of the block that has been used. |
1843 | */ | 1843 | */ |
1844 | static void | 1844 | static void |
1845 | growstackblock(void) | 1845 | growstackblock(size_t min) |
1846 | { | 1846 | { |
1847 | size_t newlen; | 1847 | size_t newlen; |
1848 | 1848 | ||
1849 | newlen = g_stacknleft * 2; | 1849 | newlen = g_stacknleft * 2; |
1850 | if (newlen < g_stacknleft) | 1850 | if (newlen < g_stacknleft) |
1851 | ash_msg_and_raise_error(bb_msg_memory_exhausted); | 1851 | ash_msg_and_raise_error(bb_msg_memory_exhausted); |
1852 | if (newlen < 128) | 1852 | min = SHELL_ALIGN(min | 128); |
1853 | newlen += 128; | 1853 | if (newlen < min) |
1854 | newlen += min; | ||
1854 | 1855 | ||
1855 | if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) { | 1856 | if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) { |
1856 | struct stack_block *sp; | 1857 | struct stack_block *sp; |
@@ -1900,16 +1901,15 @@ static void * | |||
1900 | growstackstr(void) | 1901 | growstackstr(void) |
1901 | { | 1902 | { |
1902 | size_t len = stackblocksize(); | 1903 | size_t len = stackblocksize(); |
1903 | growstackblock(); | 1904 | growstackblock(0); |
1904 | return (char *)stackblock() + len; | 1905 | return (char *)stackblock() + len; |
1905 | } | 1906 | } |
1906 | 1907 | ||
1907 | static char * | 1908 | static char * |
1908 | growstackto(size_t len) | 1909 | growstackto(size_t len) |
1909 | { | 1910 | { |
1910 | while (stackblocksize() < len) | 1911 | if (stackblocksize() < len) |
1911 | growstackblock(); | 1912 | growstackblock(len); |
1912 | |||
1913 | return stackblock(); | 1913 | return stackblock(); |
1914 | } | 1914 | } |
1915 | 1915 | ||
@@ -5962,29 +5962,36 @@ stoppedjobs(void) | |||
5962 | * the pipe without forking. | 5962 | * the pipe without forking. |
5963 | */ | 5963 | */ |
5964 | /* openhere needs this forward reference */ | 5964 | /* openhere needs this forward reference */ |
5965 | static void expandhere(union node *arg, int fd); | 5965 | static void expandhere(union node *arg); |
5966 | static int | 5966 | static int |
5967 | openhere(union node *redir) | 5967 | openhere(union node *redir) |
5968 | { | 5968 | { |
5969 | char *p; | ||
5969 | int pip[2]; | 5970 | int pip[2]; |
5970 | size_t len = 0; | 5971 | size_t len = 0; |
5971 | IF_PLATFORM_MINGW32(struct forkshell fs); | 5972 | IF_PLATFORM_MINGW32(struct forkshell fs); |
5972 | 5973 | ||
5973 | if (pipe(pip) < 0) | 5974 | if (pipe(pip) < 0) |
5974 | ash_msg_and_raise_perror("can't create pipe"); | 5975 | ash_msg_and_raise_perror("can't create pipe"); |
5975 | if (redir->type == NHERE) { | 5976 | |
5976 | len = strlen(redir->nhere.doc->narg.text); | 5977 | p = redir->nhere.doc->narg.text; |
5977 | if (len <= PIPE_BUF) { | 5978 | if (redir->type == NXHERE) { |
5978 | full_write(pip[1], redir->nhere.doc->narg.text, len); | 5979 | expandhere(redir->nhere.doc); |
5979 | goto out; | 5980 | p = stackblock(); |
5980 | } | ||
5981 | } | 5981 | } |
5982 | |||
5983 | len = strlen(p); | ||
5984 | if (len <= PIPE_BUF) { | ||
5985 | xwrite(pip[1], p, len); | ||
5986 | goto out; | ||
5987 | } | ||
5988 | |||
5982 | #if ENABLE_PLATFORM_MINGW32 | 5989 | #if ENABLE_PLATFORM_MINGW32 |
5983 | memset(&fs, 0, sizeof(fs)); | 5990 | memset(&fs, 0, sizeof(fs)); |
5984 | fs.fpid = FS_OPENHERE; | 5991 | fs.fpid = FS_OPENHERE; |
5985 | fs.n = redir; | ||
5986 | fs.fd[0] = pip[0]; | 5992 | fs.fd[0] = pip[0]; |
5987 | fs.fd[1] = pip[1]; | 5993 | fs.fd[1] = pip[1]; |
5994 | fs.path = p; | ||
5988 | spawn_forkshell(&fs, NULL, NULL, FORK_NOJOB); | 5995 | spawn_forkshell(&fs, NULL, NULL, FORK_NOJOB); |
5989 | #else | 5996 | #else |
5990 | if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { | 5997 | if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { |
@@ -5995,10 +6002,7 @@ openhere(union node *redir) | |||
5995 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); | 6002 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); |
5996 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); | 6003 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); |
5997 | signal(SIGPIPE, SIG_DFL); | 6004 | signal(SIGPIPE, SIG_DFL); |
5998 | if (redir->type == NHERE) | 6005 | xwrite(pip[1], p, len); |
5999 | full_write(pip[1], redir->nhere.doc->narg.text, len); | ||
6000 | else /* NXHERE */ | ||
6001 | expandhere(redir->nhere.doc, pip[1]); | ||
6002 | _exit(EXIT_SUCCESS); | 6006 | _exit(EXIT_SUCCESS); |
6003 | } | 6007 | } |
6004 | #endif | 6008 | #endif |
@@ -6602,26 +6606,6 @@ static struct ifsregion *ifslastp; | |||
6602 | static struct arglist exparg; | 6606 | static struct arglist exparg; |
6603 | 6607 | ||
6604 | /* | 6608 | /* |
6605 | * Our own itoa(). | ||
6606 | * cvtnum() is used even if math support is off (to prepare $? values and such). | ||
6607 | */ | ||
6608 | static int | ||
6609 | cvtnum(arith_t num) | ||
6610 | { | ||
6611 | int len; | ||
6612 | |||
6613 | /* 32-bit and wider ints require buffer size of bytes*3 (or less) */ | ||
6614 | len = sizeof(arith_t) * 3; | ||
6615 | /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */ | ||
6616 | if (sizeof(arith_t) < 4) len += 2; | ||
6617 | |||
6618 | expdest = makestrspace(len, expdest); | ||
6619 | len = fmtstr(expdest, len, ARITH_FMT, num); | ||
6620 | STADJUST(len, expdest); | ||
6621 | return len; | ||
6622 | } | ||
6623 | |||
6624 | /* | ||
6625 | * Break the argument string into pieces based upon IFS and add the | 6609 | * Break the argument string into pieces based upon IFS and add the |
6626 | * strings to the argument list. The regions of the string to be | 6610 | * strings to the argument list. The regions of the string to be |
6627 | * searched for IFS characters have been stored by recordregion. | 6611 | * searched for IFS characters have been stored by recordregion. |
@@ -6878,16 +6862,18 @@ preglob(const char *pattern, int flag) | |||
6878 | /* | 6862 | /* |
6879 | * Put a string on the stack. | 6863 | * Put a string on the stack. |
6880 | */ | 6864 | */ |
6881 | static void | 6865 | static size_t |
6882 | memtodest(const char *p, size_t len, int flags) | 6866 | memtodest(const char *p, size_t len, int flags) |
6883 | { | 6867 | { |
6884 | int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; | 6868 | int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; |
6885 | char *q; | 6869 | char *q; |
6870 | char *s; | ||
6886 | 6871 | ||
6887 | if (!len) | 6872 | if (!len) |
6888 | return; | 6873 | return 0; |
6889 | 6874 | ||
6890 | q = makestrspace(len * 2, expdest); | 6875 | q = makestrspace(len * 2, expdest); |
6876 | s = q; | ||
6891 | 6877 | ||
6892 | do { | 6878 | do { |
6893 | unsigned char c = *p++; | 6879 | unsigned char c = *p++; |
@@ -6906,6 +6892,7 @@ memtodest(const char *p, size_t len, int flags) | |||
6906 | } while (--len); | 6892 | } while (--len); |
6907 | 6893 | ||
6908 | expdest = q; | 6894 | expdest = q; |
6895 | return q - s; | ||
6909 | } | 6896 | } |
6910 | 6897 | ||
6911 | static size_t | 6898 | static size_t |
@@ -6917,6 +6904,22 @@ strtodest(const char *p, int flags) | |||
6917 | } | 6904 | } |
6918 | 6905 | ||
6919 | /* | 6906 | /* |
6907 | * Our own itoa(). | ||
6908 | * cvtnum() is used even if math support is off (to prepare $? values and such). | ||
6909 | */ | ||
6910 | static int | ||
6911 | cvtnum(arith_t num, int flags) | ||
6912 | { | ||
6913 | /* 32-bit and wider ints require buffer size of bytes*3 (or less) */ | ||
6914 | /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */ | ||
6915 | int len = (sizeof(arith_t) >= 4) ? sizeof(arith_t) * 3 : sizeof(arith_t) * 3 + 2; | ||
6916 | char buf[len]; | ||
6917 | |||
6918 | len = fmtstr(buf, len, ARITH_FMT, num); | ||
6919 | return memtodest(buf, len, flags); | ||
6920 | } | ||
6921 | |||
6922 | /* | ||
6920 | * Record the fact that we have to scan this region of the | 6923 | * Record the fact that we have to scan this region of the |
6921 | * string for IFS characters. | 6924 | * string for IFS characters. |
6922 | */ | 6925 | */ |
@@ -7225,7 +7228,7 @@ expari(int flag) | |||
7225 | if (flag & QUOTES_ESC) | 7228 | if (flag & QUOTES_ESC) |
7226 | rmescapes(p + 1, 0, NULL); | 7229 | rmescapes(p + 1, 0, NULL); |
7227 | 7230 | ||
7228 | len = cvtnum(ash_arith(p + 1)); | 7231 | len = cvtnum(ash_arith(p + 1), flag); |
7229 | 7232 | ||
7230 | if (!(flag & EXP_QUOTED)) | 7233 | if (!(flag & EXP_QUOTED)) |
7231 | recordregion(begoff, begoff + len, 0); | 7234 | recordregion(begoff, begoff + len, 0); |
@@ -7870,7 +7873,7 @@ varvalue(char *name, int varflags, int flags, int quoted) | |||
7870 | if (num == 0) | 7873 | if (num == 0) |
7871 | return -1; | 7874 | return -1; |
7872 | numvar: | 7875 | numvar: |
7873 | len = cvtnum(num); | 7876 | len = cvtnum(num, flags); |
7874 | goto check_1char_name; | 7877 | goto check_1char_name; |
7875 | case '-': | 7878 | case '-': |
7876 | expdest = makestrspace(NOPTS, expdest); | 7879 | expdest = makestrspace(NOPTS, expdest); |
@@ -8036,7 +8039,7 @@ evalvar(char *p, int flag) | |||
8036 | varunset(p, var, 0, 0); | 8039 | varunset(p, var, 0, 0); |
8037 | 8040 | ||
8038 | if (subtype == VSLENGTH) { | 8041 | if (subtype == VSLENGTH) { |
8039 | cvtnum(varlen > 0 ? varlen : 0); | 8042 | cvtnum(varlen > 0 ? varlen : 0, flag); |
8040 | goto record; | 8043 | goto record; |
8041 | } | 8044 | } |
8042 | 8045 | ||
@@ -8567,10 +8570,9 @@ expandarg(union node *arg, struct arglist *arglist, int flag) | |||
8567 | * Expand shell variables and backquotes inside a here document. | 8570 | * Expand shell variables and backquotes inside a here document. |
8568 | */ | 8571 | */ |
8569 | static void | 8572 | static void |
8570 | expandhere(union node *arg, int fd) | 8573 | expandhere(union node *arg) |
8571 | { | 8574 | { |
8572 | expandarg(arg, (struct arglist *)NULL, EXP_QUOTED); | 8575 | expandarg(arg, (struct arglist *)NULL, EXP_QUOTED); |
8573 | full_write(fd, stackblock(), expdest - (char *)stackblock()); | ||
8574 | } | 8576 | } |
8575 | 8577 | ||
8576 | /* | 8578 | /* |
@@ -12331,7 +12333,7 @@ list(int nlflag) | |||
12331 | 12333 | ||
12332 | n1 = NULL; | 12334 | n1 = NULL; |
12333 | for (;;) { | 12335 | for (;;) { |
12334 | switch (peektoken()) { | 12336 | switch (readtoken()) { |
12335 | case TNL: | 12337 | case TNL: |
12336 | if (!(nlflag & 1)) | 12338 | if (!(nlflag & 1)) |
12337 | break; | 12339 | break; |
@@ -12342,9 +12344,12 @@ list(int nlflag) | |||
12342 | if (!n1 && (nlflag & 1)) | 12344 | if (!n1 && (nlflag & 1)) |
12343 | n1 = NODE_EOF; | 12345 | n1 = NODE_EOF; |
12344 | parseheredoc(); | 12346 | parseheredoc(); |
12347 | tokpushback++; | ||
12348 | lasttoken = TEOF; | ||
12345 | return n1; | 12349 | return n1; |
12346 | } | 12350 | } |
12347 | 12351 | ||
12352 | tokpushback++; | ||
12348 | checkkwd = CHKNL | CHKKWD | CHKALIAS; | 12353 | checkkwd = CHKNL | CHKKWD | CHKALIAS; |
12349 | if (nlflag == 2 && ((1 << peektoken()) & tokendlist)) | 12354 | if (nlflag == 2 && ((1 << peektoken()) & tokendlist)) |
12350 | return n1; | 12355 | return n1; |
@@ -13601,9 +13606,9 @@ parsebackq: { | |||
13601 | if (readtoken() != TRP) | 13606 | if (readtoken() != TRP) |
13602 | raise_error_unexpected_syntax(TRP); | 13607 | raise_error_unexpected_syntax(TRP); |
13603 | setinputstring(nullstr); | 13608 | setinputstring(nullstr); |
13604 | parseheredoc(); | ||
13605 | } | 13609 | } |
13606 | 13610 | ||
13611 | parseheredoc(); | ||
13607 | heredoclist = saveheredoclist; | 13612 | heredoclist = saveheredoclist; |
13608 | 13613 | ||
13609 | (*nlpp)->n = n; | 13614 | (*nlpp)->n = n; |
@@ -15473,7 +15478,8 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
15473 | static void | 15478 | static void |
15474 | forkshell_openhere(struct forkshell *fs) | 15479 | forkshell_openhere(struct forkshell *fs) |
15475 | { | 15480 | { |
15476 | union node *redir = fs->n; | 15481 | const char *p = fs->path; |
15482 | size_t len = strlen(p); | ||
15477 | int pip[2]; | 15483 | int pip[2]; |
15478 | 15484 | ||
15479 | pip[0] = fs->fd[0]; | 15485 | pip[0] = fs->fd[0]; |
@@ -15487,11 +15493,7 @@ forkshell_openhere(struct forkshell *fs) | |||
15487 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); | 15493 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); |
15488 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); | 15494 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); |
15489 | signal(SIGPIPE, SIG_DFL); | 15495 | signal(SIGPIPE, SIG_DFL); |
15490 | if (redir->type == NHERE) { | 15496 | xwrite(pip[1], p, len); |
15491 | size_t len = strlen(redir->nhere.doc->narg.text); | ||
15492 | full_write(pip[1], redir->nhere.doc->narg.text, len); | ||
15493 | } else /* NXHERE */ | ||
15494 | expandhere(redir->nhere.doc, pip[1]); | ||
15495 | _exit(EXIT_SUCCESS); | 15497 | _exit(EXIT_SUCCESS); |
15496 | } | 15498 | } |
15497 | 15499 | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_side_effects.right b/shell/ash_test/ash-heredoc/heredoc_side_effects.right new file mode 100644 index 000000000..53b2c03c1 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_side_effects.right | |||
@@ -0,0 +1 @@ | |||
NO BUG | |||
diff --git a/shell/ash_test/ash-heredoc/heredoc_side_effects.tests b/shell/ash_test/ash-heredoc/heredoc_side_effects.tests new file mode 100755 index 000000000..3fb622ae4 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_side_effects.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | unset a | ||
2 | cat <<EOF >/dev/null | ||
3 | ${a=NO} | ||
4 | EOF | ||
5 | echo $a BUG | ||
diff --git a/shell/ash_test/ash-quoting/negative_arith.right b/shell/ash_test/ash-quoting/negative_arith.right new file mode 100644 index 000000000..e7e51eee7 --- /dev/null +++ b/shell/ash_test/ash-quoting/negative_arith.right | |||
@@ -0,0 +1,2 @@ | |||
1 | tempfile0.tmp tempfile9.tmp | ||
2 | tempfile0.tmp tempfile1.tmp tempfile9.tmp | ||
diff --git a/shell/ash_test/ash-quoting/negative_arith.tests b/shell/ash_test/ash-quoting/negative_arith.tests new file mode 100755 index 000000000..8e47ca111 --- /dev/null +++ b/shell/ash_test/ash-quoting/negative_arith.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | >tempfile0.tmp | ||
2 | >tempfile1.tmp | ||
3 | >tempfile9.tmp | ||
4 | # The [...] is interpreted as: "any of the chars 0, -, and 9" | ||
5 | echo tempfile[0"$((-9))"].tmp | ||
6 | # The [...] is [0-9], interpreted as: "any digit" | ||
7 | echo tempfile[0$((-9))].tmp | ||
8 | rm tempfile?.tmp | ||
diff --git a/shell/hush.c b/shell/hush.c index 357a354e2..0a92f5da7 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -3007,7 +3007,10 @@ static void x_mode_flush(void) | |||
3007 | static void o_addqchr(o_string *o, int ch) | 3007 | static void o_addqchr(o_string *o, int ch) |
3008 | { | 3008 | { |
3009 | int sz = 1; | 3009 | int sz = 1; |
3010 | char *found = strchr("*?[\\" MAYBE_BRACES, ch); | 3010 | /* '-' is included because of this case: |
3011 | * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9] | ||
3012 | */ | ||
3013 | char *found = strchr("*?[-\\" MAYBE_BRACES, ch); | ||
3011 | if (found) | 3014 | if (found) |
3012 | sz++; | 3015 | sz++; |
3013 | o_grow_by(o, sz); | 3016 | o_grow_by(o, sz); |
@@ -3024,7 +3027,7 @@ static void o_addQchr(o_string *o, int ch) | |||
3024 | { | 3027 | { |
3025 | int sz = 1; | 3028 | int sz = 1; |
3026 | if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) | 3029 | if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) |
3027 | && strchr("*?[\\" MAYBE_BRACES, ch) | 3030 | && strchr("*?[-\\" MAYBE_BRACES, ch) |
3028 | ) { | 3031 | ) { |
3029 | sz++; | 3032 | sz++; |
3030 | o->data[o->length] = '\\'; | 3033 | o->data[o->length] = '\\'; |
@@ -3041,7 +3044,7 @@ static void o_addqblock(o_string *o, const char *str, int len) | |||
3041 | while (len) { | 3044 | while (len) { |
3042 | char ch; | 3045 | char ch; |
3043 | int sz; | 3046 | int sz; |
3044 | int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES); | 3047 | int ordinary_cnt = strcspn(str, "*?[-\\" MAYBE_BRACES); |
3045 | if (ordinary_cnt > len) /* paranoia */ | 3048 | if (ordinary_cnt > len) /* paranoia */ |
3046 | ordinary_cnt = len; | 3049 | ordinary_cnt = len; |
3047 | o_addblock(o, str, ordinary_cnt); | 3050 | o_addblock(o, str, ordinary_cnt); |
@@ -3052,7 +3055,7 @@ static void o_addqblock(o_string *o, const char *str, int len) | |||
3052 | 3055 | ||
3053 | ch = *str++; | 3056 | ch = *str++; |
3054 | sz = 1; | 3057 | sz = 1; |
3055 | if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */ | 3058 | if (ch) { /* it is necessarily one of "*?[-\\" MAYBE_BRACES */ |
3056 | sz++; | 3059 | sz++; |
3057 | o->data[o->length] = '\\'; | 3060 | o->data[o->length] = '\\'; |
3058 | o->length++; | 3061 | o->length++; |
@@ -5049,7 +5052,7 @@ static int parse_dollar(o_string *as_string, | |||
5049 | ch = i_getch(input); | 5052 | ch = i_getch(input); |
5050 | nommu_addchr(as_string, ch); | 5053 | nommu_addchr(as_string, ch); |
5051 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 5054 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
5052 | o_addchr(dest, /*quote_mask |*/ '+'); | 5055 | o_addchr(dest, quote_mask | '+'); |
5053 | if (!BB_MMU) | 5056 | if (!BB_MMU) |
5054 | pos = dest->length; | 5057 | pos = dest->length; |
5055 | if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG)) | 5058 | if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG)) |
@@ -6851,6 +6854,17 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) | |||
6851 | res = expand_and_evaluate_arith(arg, NULL); | 6854 | res = expand_and_evaluate_arith(arg, NULL); |
6852 | debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); | 6855 | debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); |
6853 | sprintf(arith_buf, ARITH_FMT, res); | 6856 | sprintf(arith_buf, ARITH_FMT, res); |
6857 | if (res < 0 | ||
6858 | && first_ch == (char)('+'|0x80) | ||
6859 | /* && (output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) */ | ||
6860 | ) { | ||
6861 | /* Quoted negative ariths, like filename[0"$((-9))"], | ||
6862 | * should not be interpreted as glob ranges. | ||
6863 | * Convert leading '-' to '\-': | ||
6864 | */ | ||
6865 | o_grow_by(output, 1); | ||
6866 | output->data[output->length++] = '\\'; | ||
6867 | } | ||
6854 | o_addstr(output, arith_buf); | 6868 | o_addstr(output, arith_buf); |
6855 | break; | 6869 | break; |
6856 | } | 6870 | } |
diff --git a/shell/hush_test/hush-quoting/negative_arith.right b/shell/hush_test/hush-quoting/negative_arith.right new file mode 100644 index 000000000..e7e51eee7 --- /dev/null +++ b/shell/hush_test/hush-quoting/negative_arith.right | |||
@@ -0,0 +1,2 @@ | |||
1 | tempfile0.tmp tempfile9.tmp | ||
2 | tempfile0.tmp tempfile1.tmp tempfile9.tmp | ||
diff --git a/shell/hush_test/hush-quoting/negative_arith.tests b/shell/hush_test/hush-quoting/negative_arith.tests new file mode 100755 index 000000000..8e47ca111 --- /dev/null +++ b/shell/hush_test/hush-quoting/negative_arith.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | >tempfile0.tmp | ||
2 | >tempfile1.tmp | ||
3 | >tempfile9.tmp | ||
4 | # The [...] is interpreted as: "any of the chars 0, -, and 9" | ||
5 | echo tempfile[0"$((-9))"].tmp | ||
6 | # The [...] is [0-9], interpreted as: "any digit" | ||
7 | echo tempfile[0$((-9))].tmp | ||
8 | rm tempfile?.tmp | ||