Re: [PATCH] jobs: Block signals during tcsetpgrp
On Wed, Jan 6, 2021 at 10:17 PM Harald van Dijk wrote: > On 06/01/2021 04:45, Herbert Xu wrote: > > This patch implements the blocking of SIGTTOU (and everything else) > > while we call tcsetpgrp. > > > > Reported-by: Steffen Nurpmeso > > Signed-off-by: Herbert Xu > > > > diff --git a/src/jobs.c b/src/jobs.c > > index 516786f..809f37c 100644 > > --- a/src/jobs.c > > +++ b/src/jobs.c > > @@ -1512,7 +1512,13 @@ showpipe(struct job *jp, struct output *out) > > STATIC void > > xtcsetpgrp(int fd, pid_t pgrp) > > { > > - if (tcsetpgrp(fd, pgrp)) > > + int err; > > + > > + sigblockall(NULL); > > + err = tcsetpgrp(fd, pgrp); > > + sigclearmask(); > > + > > + if (err) > > sh_error("Cannot set tty process group (%s)", > > strerror(errno)); > > } > > #endif > > While this is a step in the right direction, Jilles has already replied > with an explanation of why this is not enough: if the terminal is in > TOSTOP mode, it's not just tcsetpgrp() that needs to be handled, it's > any write as well that may occur while the shell is not in the > foreground process group. While it may be working according to design > for messages written when the shell is not supposed to be in the > foreground process group, it is another story when the shell is both > responsible for taking itself out of the foreground process group and > for writing a message. This is made worse by the fact that there is no > synchronisation with child processes on errors, so even forcibly > restoring the foreground process group may not be enough: unfortunate > scheduling may result in a child process immediately setting the > foreground process group to the child process after the parent process > attempted to restore it to itself. I have not yet seen a good solution > for this. How about not simply allowing traps on SIGTTOU, like other shells do? It's not like there is real-world need to allow usage of this signal - it's not customarily used by userspace for inter-process signaling, unlike e.g. SIGTERM or SIGUSR1/2.
set -i, -s do not make sense, bash does not accept them
Hello, dash accepts "set -i" and "set -s", and their +OPT forms. The -s/+s does not seem to do anything except affecting the value of $-. The -i/+i does have some effects. In interactive shell, "set +i" makes prompt disappear. In non-interactive shell, "set -i" makes it possible to ^C break the script and land user into interactive input prompt (!): $ PS1='T>' dash -c 'set -i; echo $-; sleep 5; echo $-' i ^C T> _ >From code inspection, this seems to be caused by 's' and 'i' being present in optletters[] array, and parsing code treating them as "set" options, not special-cased. IOW: it does not appear to be intentional. bash does not treat them as "set" options. They are only valid in startup command line, not in "set" command. dash does the same with -c option. bash adds "i", "s" and "c" into the value of $-, despite them not being "set" options. dash does not do so, resulting in discrepancy of not showing "c" if e.g. "dash -c 'echo $-'" is run. I propose to mimic bash behavior more closely: do not accept "set -i" and "set -s", show "c" in $-.
set -I is not required by standard, and does not match bash
Hello, In dash, set -I is a short-option alias to set -o ignoreeof. However, bash does not have such alias, it has an undocumented set -I which switches off "invisible variables" (I don't know what that is). Standards do not mention any -I option. I propose, in the interests of keeping things less disparate, to remove set -I support from dash: make "ignoreeof" to be only an -o long option.
ungetc is not cleared on error?
Current git: $ ;l dash: 1: Syntax error: ";" unexpected $ s COPYINGChangeLog.OMakefile.am aclocal.m4 autom4te.cache config.h config.log configure dash dollar_altvalue1.tests missing stamp-h1 ChangeLog MakefileMakefile.in autogen.sh compile config.h.in config.status configure.ac depcomp install-sh src trace
Fwd: Busybox ash buffering-related issue in error handling
This bug happens in dash too (I assume it's "pungets" counter not being reset on errors): -- Forwarded message - From: Sergey Zakharchenko Date: Thu, Oct 29, 2020 at 8:00 AM Subject: Busybox ash buffering-related issue in error handling To: Denys Vlasenko It appears that, in the interactive shell, the input buffer has 1 last character remaining after some syntax errors are handled. The next command is interpreted with that character prepended, e.g.: $ ;l ash: syntax error: unexpected ";" $ s [ls output] Expected output for reference: $ ;l sh: 1: Syntax error: ";" unexpected $ s sh: 1: s: not found Similarly, an input of ;# makes the next command be treated as a comment and not executed. I'm observing this on x86-64 112453acf24520b4655f9f36da41d8ac591b1a60, with default options, but it's the same on earlier versions with different options and a different platform so it's not new. Best regards, -- Sergey Zakharchenko Digital Loggers, Inc.
[PATCH] Remove unused expandmeta() flag parameter
Signed-off-by: Denys Vlasenko --- src/expand.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/expand.c b/src/expand.c index 4a5d75a..985cd70 100644 --- a/src/expand.c +++ b/src/expand.c @@ -118,7 +118,7 @@ STATIC char *evalvar(char *, int); static size_t strtodest(const char *p, int flags); static size_t memtodest(const char *p, size_t len, int flags); STATIC ssize_t varvalue(char *, int, int, int); -STATIC void expandmeta(struct strlist *, int); +STATIC void expandmeta(struct strlist *); #ifdef HAVE_GLOB STATIC void addglob(const glob_t *); #else @@ -205,7 +205,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag) ifsbreakup(p, -1, ); *exparg.lastp = NULL; exparg.lastp = - expandmeta(exparg.list, flag); + expandmeta(exparg.list); } else { sp = (struct strlist *)stalloc(sizeof (struct strlist)); sp->text = p; @@ -1155,9 +1155,7 @@ out: #ifdef HAVE_GLOB STATIC void -expandmeta(str, flag) - struct strlist *str; - int flag; +expandmeta(struct strlist *str) { /* TODO - EXP_REDIR */ @@ -1221,7 +1219,7 @@ STATIC unsigned expdir_max; STATIC void -expandmeta(struct strlist *str, int flag) +expandmeta(struct strlist *str) { static const char metachars[] = { '*', '?', '[', 0 -- 2.25.0
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Mon, Apr 2, 2018 at 7:08 PM, Herbert Xu <herb...@gondor.apana.org.au> wrote: > On Mon, Apr 02, 2018 at 03:48:46PM +0200, Denys Vlasenko wrote: >> >> Another probably buggy case: >> >> cat <> -\t-\\-\"-\'-\`-\--\z-\*-\?- >> `echo '-\t-\\-\"-\x-\`-\--\z-\*-\?-'` >> $(echo '-\t-\\-\"-\x-\`-\--\z-\*-\?-') >> EOF >> >> >> # bash heredoc_backslash.test >> -\t-\-\"-\'-`-\--\z-\*-\?- >> -\t-\-\"-\x-`-\--\z-\*-\?- >> -\t-\\-\"-\x-\`-\--\z-\*-\?- >> >> # dash heredoc_backslash.test >> -\t-\-\"-\'-`-\--\z-\*-\?- >> --\-"-\x-`-\--\z-\*-\?- >> --\-\"-\x-\`-\--\z-\*-\?- >> >> (Second and third line have \t expanded to tab. Mail-mangled to spaces, >> likely) >> >> Apart from \t, note that in second heredoc line there is a difference in how >> `echo '\"'` was handled: bash prints \", dash prints ". > > FWIW ksh93 does the same thing. Building and launching current git... sh-4.3$ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean sh-4.3$ git pull Already up to date. sh-4.3$ make make all-recursive ... make[2]: Leaving directory '/home/srcdevel/bbox/fix/dash-T' make[1]: Leaving directory '/home/srcdevel/bbox/fix/dash-T' sh-3.4$ src/dash I see this: $ x='\t'; echo "[$x]" [] I'm pretty sure this isn't okay... -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Sat, Mar 10, 2018 at 3:04 AM, Harald van Dijkwrote: > On 3/8/18 1:40 AM, Harald van Dijk wrote: >> >> If the syntax stack is to be stored on the actual stack, then real >> recursion could be used instead, as attached. > > > Even though it won't be accepted in dash, I continued with this approach for > my own use. I've now got it to about 1800 bytes smaller (at -Os -s). > > After the other changes I'd done, it became apparent to me that the syntax > tables were unnecessary, and that they'd become fairly easy to get rid of. > This was a big space saver that may be possible to apply to your version as > well. I ported all recent dash commits to bbox ash. Nice! I indeed feel that recursion is better implemented via function stack recursion rather than linked list of alloca()ed structs. Poor gcc has hard time optimizing readtoken1() atrocity as it stands. I was trying some of the beautiful atrocities from one of earlier Harald's emails and this one fails in current dash git: # x=""; echo "${x#"${x+''}"''}" dash: 12: Syntax error: Missing '}' -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
"parser: Fix backquote support in here-document EOF mark" incomplete
Hi Herbert, Regarding: commit c166b718b496da63c4df7a0972df2fc6cd38256b Author: Herbert XuDate: Thu Mar 15 18:27:30 2018 +0800 parser: Fix backquote support in here-document EOF mark I discovered that bash, on encountering `` in eof mark, also treats eof mark as quoted. Testcase (initially intended to test that `cmd` is not expanded, but taken literally): cat <
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Fri, Mar 2, 2018 at 7:03 PM, Harald van Dijk <har...@gigawatt.nl> wrote: > On 02/03/2018 18:00, Denys Vlasenko wrote: >> >> On Wed, Feb 14, 2018 at 9:03 PM, Harald van Dijk <har...@gigawatt.nl> >> wrote: >>> >>> Currently: >>> >>> $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' >>> <> >>> >>> This is what I expect, and also what bash, ksh and posh do. >>> >>> With your patch: >>> >>> $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' >>> >> >> I was looking into this specific example and I believe it is a _bash_ bug. >> >> The [a\]] is misinterpreted by it (and probably by many people). >> The gist is: \] is not a valid escape for ] in set glob expression. >> Glob sets have no escaping at all, ] can be in a set >> if it is the first char: []abc], >> dash can be in a set if it is first or last: [abc-], >> [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. >> >> Therefore, "[a\]]" glob pattern means "a or \, then ]". >> Since that does not match "a", the result of ${foo#[a\]]}> should be "a". > > Are you sure about this? "Patterns Matching a Single Character"'s first > paragraph contains "A character shall escape the following > character. The escaping shall be discarded." The shell does this > first. I have problems with "The shell does this first" statement. It's useful to view the entire discussion of glob pattern matching as a discussion of how fnmatch(pattern, string, flags) should behave (even if a particular shell implementation chose to not use C library's fnmatch() to implement its globbing). Otherwise (IOW: if you allow gobbing to depend on shell's quoting), rules for globbing for different applications will not be consistent. Which would be bad. As I see it, shell should massage input according to shell rules (quote/bkslash removal et al), then use fnmatch() or glob(), or its own internal implementations of them. bash seems to not do it. It probably has a "combined" routine which does both in one step, which allows quote removal to interfere with globbing. Here's the proof: $ x='a]'; echo _${x#[a\]]}_ _]_ In the above code, what pattern should be fed to fnmatch(), assuming shell uses fnmatch() to implement ${x#pattern}? Pattern should be "[a]]" because by shell rules "\]" in an unquoted string is "]". But try this: $ x='a]'; echo _${x#[a]]}_ __ Here, pattern should be "[a]]" as well - it literally is. But the results are different! Evidently, bash does _not_ perform quote removal (more precisely, backslash removal) on pattern string. Somehow, globbing code knows \ was there. (And this globbing code, in my opinion, also misinterprets [a\]] as "set of 'a' or ']'", but (a) I might be wrong on this, and (b) this is a bit offtopic, we discuss ${x#pattern} handling here). To me, it looks that bash behavior is buggy regardless of what \] means in glob patterns. These two should be equivalent: x='a]'; echo _${x#[a\]]}_ x='a]'; echo _${x#[a]]}_ because they should use the same pattern for globbing match. Alternative possibility is that pattern in ${x#pattern} is not handled by the usual shell rules: backslashes are not removed. This would be VERY ugly as soon as nested variable expansions are considered. -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Wed, Feb 14, 2018 at 9:03 PM, Harald van Dijkwrote: > Currently: > > $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' > <> > > This is what I expect, and also what bash, ksh and posh do. > > With your patch: > > $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' > I was looking into this specific example and I believe it is a _bash_ bug. The [a\]] is misinterpreted by it (and probably by many people). The gist is: \] is not a valid escape for ] in set glob expression. Glob sets have no escaping at all, ] can be in a set if it is the first char: []abc], dash can be in a set if it is first or last: [abc-], [ and \ need no protections at all: [a[b\c] is a valid set of 5 chars. Therefore, "[a\]]" glob pattern means "a or \, then ]". Since that does not match "a", the result of ${foo#[a\]]}> should be "a". -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Sat, Feb 24, 2018 at 5:52 PM, Herbert Xuwrote: > On Sat, Feb 24, 2018 at 10:47:07AM +0100, Harald van Dijk wrote: >> >> It seems like the new control character doesn't get escaped in one place >> where it should be, and gets lost because of that: >> >> Unpatched: >> >> $ dash -c 'x=`printf \\\211X`; echo $x | cat -v' >> M-^IX >> >> Patched: >> >> $ src/dash -c 'x=`printf \\\211X`; echo $x | cat -v' >> X > > Hmm, it works here. Can you check that your Makefile is up-to-date > and the generated syntax.c looks like this: > > const char basesyntax[] = { > CEOF,CSPCL, CWORD, CCTL, > CCTL,CCTL,CCTL,CCTL, > CCTL,CCTL,CCTL,CCTL, > > Cheers, Guys, while you work on fixing this, consider taking a look at some more parsing cases in this bbox bug: https://bugs.busybox.net/show_bug.cgi?id=10821 I suppose some of them may fail in dash too (I did not test, sorry). -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: dash bug: double-quoted "\" breaks glob protection for next char
On Mon, Feb 19, 2018 at 11:13 PM, Harald van Dijk <har...@gigawatt.nl> wrote: > On 2/18/18 11:50 PM, Harald van Dijk wrote: >> On 2/14/18 11:50 PM, Harald van Dijk wrote: >>> On 2/14/18 10:44 PM, Harald van Dijk wrote: >>>> On 2/14/18 9:03 PM, Harald van Dijk wrote: >>>>> On 13/02/2018 14:53, Denys Vlasenko wrote: >>>>>> $ >'\' >>>>>> $ >'\' >>>>>> $ dash -c 'echo "\*"' >>>>>> \ \ >>>>> >>>>> >>>>> [...] >>>>> >>>>> Currently: >>>>> >>>>> $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' >>>>> <> >>>>> >>>>> This is what I expect, and also what bash, ksh and posh do. >>>>> >>>>> With your patch: >>>>> >>>>> $ dash -c 'foo=a; echo "<${foo#[a\]]}>"' >>>>> >>>> >>>> Does the attached look right as an alternative? It treats a quoted >>>> backslash the same way as if it were preceded by CTLESC in _rmescapes. It >>>> passes your test case and mine, but I'll do more extensive testing. >>> >>> It causes preglob's string to potentially grow larger than the original. >>> When called with RMESCAPE_ALLOC, that can be handled by increasing the >>> buffer size, but preglob also gets called without RMESCAPE_ALLOC to modify a >>> string in-place. That's never going to work with this approach. Back to the >>> drawing board... >> >> There is a way to make it work: ensure sufficient memory is always >> available. Instead of inserting CTLESC, which caused problems, >> CTLQUOTEMARK+CTLQUOTEMARK can be inserted instead. It's effectively a no-op >> here. > > It required one obvious additional trivial change to the CHECKSTRSPACE > invocation, but with that added, the attached passed all testing I could > think of. Does this look okay to include, did I miss something, or is there > perhaps a better alternative? I propose replacing this: if (*p == (char)CTLESC) { p++; + goto escape; + } else if (*p == '\\') { + if (inquotes) { +escape: + if (notescaped) + *q++ = '\\'; + } else { + /* naked back slash */ + notescaped = 0; + goto copy; + } with equivalent if (*p == (char)CTLESC) { p++; + goto escape; + } + if (*p == '\\') { + if (!inquotes) { + /* naked back slash */ + notescaped = 0; + goto copy; + } +escape: + if (notescaped) + *q++ = '\\'; -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
dash bug: double-quoted "\" breaks glob protection for next char
$ >'\' $ >'\' $ dash -c 'echo "\*"' \ \ The cause: uses "\\*" pattern instead of "\\\*". The fix: /* backslash */ case CBACK: c = pgetc2(); if (c == PEOF) { USTPUTC(CTLESC, out); USTPUTC('\\', out); pungetc(); } else if (c == '\n') { nlprompt(); } else { if ( dblquote && c != '\\' && c != '`' && c != '$' && ( c != '"' || eofmark != NULL ) ) { USTPUTC(CTLESC, out); // add this line USTPUTC('\\', out); } USTPUTC(CTLESC, out); USTPUTC(c, out); quotef++; } -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [BUG] Interactive (d)ash exits on assigning to readonly from 'command eval'
On Sat, Oct 29, 2016 at 8:22 PM, Harald van Dijk <har...@gigawatt.nl> wrote: > On 28/10/16 15:55, Denys Vlasenko wrote: >> >> This will probably be mangled by gmail, but here is the proposed fix: > > > This looks about the right approach, but it causes problems in subshells, a > double free: > > $ ./busybox ash -c 'readonly x; echo $(command eval x=2)' > ash: eval: line 1: x: is read only > *** Error in `./busybox': free(): invalid pointer: 0x55a784c1c300 *** > [...] > > That's with busybox checked out from git (commit > 9db74e49e5b462089c6eec0182d819c0d4708e57), where your patch is applied, > completely unpatched and completely default config. > > I omitted the backtrace output, but it's popfile() getting called, after > popallfiles() has already been called. Thanks! Hopefully fixed in git, please try it. -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [BUG] Interactive (d)ash exits on assigning to readonly from 'command eval'
This will probably be mangled by gmail, but here is the proposed fix: Date: Fri, 28 Oct 2016 15:43:50 +0200 Subject: [PATCH] ash: fix interactive "command eval STRING" exiting on errors. This bug is also present in current dash Signed-off-by: Denys Vlasenko <vda.li...@googlemail.com> --- shell/ash.c | 25 - shell/ash_test/ash-vars/readonly1.right | 2 ++ shell/ash_test/ash-vars/readonly1.tests | 7 +++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 shell/ash_test/ash-vars/readonly1.right create mode 100755 shell/ash_test/ash-vars/readonly1.tests diff --git a/shell/ash.c b/shell/ash.c index 1ef02b8..fe11245 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2180,6 +2180,7 @@ setvareq(char *s, int flags) if (flags & VNOSAVE) free(s); n = vp->var_text; +exitstatus = 1; ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n); } @@ -9599,7 +9600,7 @@ evalcommand(union node *cmd, int flags) if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { if (exception_type == EXERROR && spclbltin <= 0) { FORCE_INT_ON; -break; +goto readstatus; } raise: longjmp(exception_handler->loc, 1); @@ -12280,6 +12281,10 @@ expandstr(const char *ps) static int evalstring(char *s, int flags) { +struct jmploc *volatile savehandler = exception_handler; +struct jmploc jmploc; +int ex; + union node *n; struct stackmark smark; int status; @@ -12289,6 +12294,19 @@ evalstring(char *s, int flags) setstackmark(); status = 0; +/* On exception inside execution loop, we must popfile(). + * Try interactively: + *readonly a=a + *command eval "a=b" # throws "is read only" error + * "command BLTIN" is not supposed to abort (even in non-interactive use). + * But if we skip popfile(), we hit EOF in eval's string, and exit. + */ +savehandler = exception_handler; +exception_handler = +ex = setjmp(jmploc.loc); +if (ex) +goto out; + while ((n = parsecmd(0)) != NODE_EOF) { int i; @@ -12299,10 +12317,15 @@ evalstring(char *s, int flags) if (evalskip) break; } + out: popstackmark(); popfile(); stunalloc(s); +exception_handler = savehandler; +if (ex) +longjmp(exception_handler->loc, ex); + return status; } diff --git a/shell/ash_test/ash-vars/readonly1.right b/shell/ash_test/ash-vars/readonly1.right new file mode 100644 index 000..2b363e3 --- /dev/null +++ b/shell/ash_test/ash-vars/readonly1.right @@ -0,0 +1,2 @@ +One:1 +One:1 diff --git a/shell/ash_test/ash-vars/readonly1.tests b/shell/ash_test/ash-vars/readonly1.tests new file mode 100755 index 000..81b461f --- /dev/null +++ b/shell/ash_test/ash-vars/readonly1.tests @@ -0,0 +1,7 @@ +readonly bla=123 +# Bare "eval bla=123" should abort ("eval" is a special builtin): +(eval bla=123 2>/dev/null; echo BUG) +echo One:$? +# "command BLTIN" disables "special-ness", should not abort: +command eval bla=123 2>/dev/null +echo One:$? -- 2.9.2 -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Bug? "fstat64(f, ) < 0 && S_ISREG(sb.st_mode)"
/* Take care of noclobber mode. */ if (Cflag) { fname = redir->nfile.expfname; if (stat64(fname, ) < 0) { if ((f = open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) goto ecreate; } else if (!S_ISREG(sb.st_mode)) { if ((f = open64(fname, O_WRONLY, 0666)) < 0) goto ecreate; if (fstat64(f, ) < 0 && S_ISREG(sb.st_mode)) { ^^ was it meant to be "fstat64(f, ) < 0 || S_ISREG(sb.st_mode)" ? close(f); errno = EEXIST; goto ecreate; } } else { errno = EEXIST; goto ecreate; } break; } -- To unsubscribe from this list: send the line "unsubscribe dash" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
dash tested against ash testsuite: 17 failures
ash-signals/savetrap.tests While trying to port some fixes from dash, one of them broke some signal handling testcases. I guess some of things we test for are not tested by dash developers. I ran entire ash testsuite against dash, deleted failing things which dash does not support (some bashisms), and false positives caused by differences in error messages. What's left is: ash-glob/glob2.tests: Evidently, dash supports \f -> ^L escape. This test uses \f as invalid backslash escape, hence differences. ash-misc/echo_write_error.tests EPIPE errors in echo are not reported ash-misc/func2.tests $((i++)) not supported ash-misc/local1.tests Doesn't unset as described: local a # the above line unsets $a echo "A2:'$a'" ash-misc/shift1.tests "shift N" fails if fewer than N argv[i] exists (likely not a bug, but bash does it differently) ash-redir/redir.tests echo errors due to closed stdout are not reported ash-redir/redir3.tests "echo foo >&9" correctly says "9: Bad file descriptor" and exitcode is 2 (in bash, it is 1). ash-redir/redir7.tests ash-redir/redir8.tests uni\x81code filename is not found by uni?code glob pattern. ash-signals/reap1.tests Builtins never wait for children. This loop will not ever stop: sleep 1 & PID=$! while kill -0 $PID >/dev/null 2>&1; do true done ash-signals/savetrap.tests `trap` does not work as expected ash-signals/sigint1.tests trap "exit 0" SIGINT - does not like name "SIGINT". "INT" works. ash-signals/signal4.tests trap "echo Trapped" BADNAME TERM - abort seeing BADNAME. bash complains, but sets the trap for the second signal. ash-signals/signal8.tests "kill %1" in non-interactive shell does not find previously backgrounded task. ash-vars/var-utf8-length.tests ${#VAR} counts unicode chars in bash ash-vars/var_unbackslash.tests b=-$a-\t-\\-\"-\`-\--\z-\*-\?- b="-$a-\t-\\-\"-\`-\--\z-\*-\?-" b='-$a-\t-\\-\"-\`-\--\z-\*-\?-' b1=$b "b1=$b" You can imagine... not everything went well here... ash-vars/var_unbackslash.tests echo Forty two:$\ (\ (\ 42\ )\ ) dash says: Syntax error: Missing '))' The tarball is attached. Unpack, add an ash -> /path/to/your/dash symlink, then run ./run-all ash_test.tar.gz Description: GNU Zip compressed data