[PATCH 4/6] eval: Avoid crash when redirecting to file descriptor in expredir

2018-09-07 Thread Andrej Shadura
From: Bernhard Übelacker 

When trying to redirect output to a filedescriptor contained in an
environment variable, but if that variable is empty, dash crashes
with a segmentation fault. To reproduce, run the following:

echo test >&$EMPTY_VARIABLE

Signed-off-by: Andrej Shadura 
Bug-Debian: https://bugs.debian.org/861354
---
 src/eval.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/eval.c b/src/eval.c
index 6185db4..ee43fa9 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -516,6 +516,7 @@ expredir(union node *n)
 
for (redir = n ; redir ; redir = redir->nfile.next) {
struct arglist fn;
+   fn.list = NULL;
fn.lastp = 
switch (redir->type) {
case NFROMTO:
@@ -530,6 +531,8 @@ expredir(union node *n)
case NTOFD:
if (redir->ndup.vname) {
expandarg(redir->ndup.vname, , EXP_FULL | 
EXP_TILDE);
+   if (!fn.list)
+   sh_error("ambiguous redirect");
fixredir(redir, fn.list->text, 1);
}
break;
-- 
2.17.1



[PATCH 3/6] mkbuiltins: Default to mktemp, not tempfile

2018-09-07 Thread Andrej Shadura
Don't use tempfile, as it currently runs tempnam(), which is insecure
and fails under pseudo(1).

Signed-off-by: Andrej Shadura 
---
 src/mkbuiltins | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mkbuiltins b/src/mkbuiltins
index b4d6f4e..f1f2593 100644
--- a/src/mkbuiltins
+++ b/src/mkbuiltins
@@ -35,7 +35,7 @@
 #
 #  @(#)mkbuiltins  8.2 (Berkeley) 5/4/95
 
-tempfile=tempfile
+tempfile=mktemp
 if ! type tempfile > /dev/null 2>&1 && ! type mktemp > /dev/null 2>&1; then
_my_tempfile()
{
-- 
2.17.1



[PATCH 1/6] exec: Don't execute binary files if execve() returned ENOEXEC.

2018-09-07 Thread Andrej Shadura
From: Adam Borowski 

Both "dash -c foo" and "./foo" are supposed to be able to run hashbang-less
scripts, but attempts to execute common binary files tend to be nasty:
especially both ELF and PE tend to make dash create a bunch of files with
unprintable names, that in turn confuse some tools up to causing data loss.

Thus, let's read the first line and see if it looks like text.  This is a
variant of the approach used by bash and zsh; mksh instead checks for
signatures of a bunch of common file types.

POSIX says: "If the executable file is not a text file, the shell may bypass
this command execution."

Signed-off-by: Adam Borowski 
Signed-off-by: Andrej Shadura 
---
 src/exec.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/src/exec.c b/src/exec.c
index 9d0215a..631 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -148,6 +148,36 @@ shellexec(char **argv, const char *path, int idx)
 }
 
 
+/*
+ * Check if an executable that just failed with ENOEXEC shouldn't be
+ * considered a script (wrong-arch ELF/PE, junk accidentally set +x, etc).
+ * We check only the first line to allow binaries encapsulated in a shell
+ * script without proper quoting.  The first line, if not a hashbang, is
+ * likely to contain comments; even ancient encodings, at least popular
+ * ones, don't use 0x7f nor values below 0x1f other than whitespace (\t,
+ * \n, \v, \f, \r), ISO/IEC 2022 can have SI, SO and \e.
+ */
+STATIC int file_is_binary(const char *cmd)
+{
+   char buf[128];
+   int fd = open(cmd, O_RDONLY|O_NOCTTY);
+   if (fd == -1)
+   return 1;
+   int len = read(fd, buf, sizeof(buf));
+   close(fd);
+   for (int i = 0; i < len; ++i) {
+   char c = buf[i];
+   if (c >= 0 && c <= 8 ||
+   c >= 16 && c <= 31 && c != 27 ||
+   c == 0x7f)
+   return 1;
+   if (c == '\n')
+   return 0;
+   }
+   return 0;
+}
+
+
 STATIC void
 tryexec(char *cmd, char **argv, char **envp)
 {
@@ -162,6 +192,8 @@ repeat:
execve(cmd, argv, envp);
 #endif
if (cmd != path_bshell && errno == ENOEXEC) {
+   if (file_is_binary(cmd))
+   return;
*argv-- = cmd;
*argv = cmd = path_bshell;
goto repeat;
-- 
2.17.1



Debian patches for dash

2018-09-07 Thread Andrej Shadura
Hi,

I’m submitting the patches we’ve had applied to dash in Debian for some
time. I have rewritten the patch descriptions to include more
information from the bug reports to make sure commit messages make more
sense and help understand the purpose of the changes.

I hope you find those patches useful and apply them upstream.

Thanks!

-- 
Cheers,
  Andrej




[PATCH 5/6] eval: Report I/O error on stdout

2018-09-07 Thread Andrej Shadura
From: Gerrit Pape 

ENOSPC as a result of an echo builting failing gives no diagnostic.
Just as other shells, dash sets $? to 1, but aside from terminating
the script, this does not inform the user what the problem is:

zsh:
% echo foo > /dev/full
echo: write error: no space left on device

bash:
$ echo foo > /dev/full
bash: echo: write error: No space left on device

dash:
$ echo foo > /dev/full
[nothing]

Print an error to stderr like the other shells.

Suggested by Roger Leigh.

Signed-off-by: Gerrit Pape 
[reworded the patch description with information from the bug]
Signed-off-by: Andrej Shadura 
Bug-Debian: http://bugs.debian.org/690473
---
 src/eval.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/eval.c b/src/eval.c
index ee43fa9..231d3e0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -955,6 +955,8 @@ evalbltin(const struct builtincmd *cmd, int argc, char 
**argv, int flags)
else
status = (*cmd->builtin)(argc, argv);
flushall();
+   if (outerr(out1))
+   warnx("%s: I/O error", commandname);
status |= outerr(out1);
exitstatus = status;
 cmddone:
-- 
2.17.1



[PATCH 2/6] printf: Support \e in "echo" and "printf" builtins.

2018-09-07 Thread Andrej Shadura
From: Adam Borowski 

dash's builtin version of printf doesn't support '\e' (escape), and literaly
outputs the 2 characters as-is. As is well known, this sequence is useful,
for example, when outputting ANSI escape sequences.

While it seems that POSIX does not require that printf support '\e',
it is still worth implementing '\e' support, as a way to make the environment
more consistent and avoid this small issue when porting scripts from certain
other systems or when migrating from bash to dash.

Signed-off-by: Adam Borowski 
[reworded the patch description]
Signed-off-by: Andrej Shadura 
Bug-Debian: http://bugs.debian.org/816295
---
 src/bltin/printf.c | 1 +
 src/dash.1 | 4 
 2 files changed, 5 insertions(+)

diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index 7785735..9b878da 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -340,6 +340,7 @@ conv_escape(char *str, int *conv_ch)
case '\\':  value = '\\';   break;  /* backslash */
case 'a':   value = '\a';   break;  /* alert */
case 'b':   value = '\b';   break;  /* backspace */
+   case 'e':   value = '\e';   break;  /* escape */
case 'f':   value = '\f';   break;  /* form-feed */
case 'n':   value = '\n';   break;  /* newline */
case 'r':   value = '\r';   break;  /* carriage-return */
diff --git a/src/dash.1 b/src/dash.1
index 32f6ac0..b286f79 100644
--- a/src/dash.1
+++ b/src/dash.1
@@ -1201,6 +1201,8 @@ Subsequent output is suppressed.  This is normally used 
at the end of the
 last argument to suppress the trailing newline that
 .Ic echo
 would otherwise output.
+.It Li \ee
+Outputs an escape character (ESC).
 .It Li \ef
 Output a form feed.
 .It Li \en
@@ -1570,6 +1572,8 @@ The characters and their meanings are as follows:
 Write a \*[Lt]bell\*[Gt] character.
 .It Cm \eb
 Write a \*[Lt]backspace\*[Gt] character.
+.It Cm \ee
+Write an \*[Lt]escape\*[Gt] (ESC) character.
 .It Cm \ef
 Write a \*[Lt]form-feed\*[Gt] character.
 .It Cm \en
-- 
2.17.1