259 Commits

Author SHA1 Message Date
Jilles Tjoelker
09683f46b9 sh: Check if dup2 for redirection from/to a file succeeds.
A failure (e.g. caused by ulimit -n being set very low) is a redirection
error.

Example:
  ulimit -n 9; exec 9<.
2010-12-31 18:20:17 +00:00
Jilles Tjoelker
11535bdf04 sh: Avoid side effects from builtins in optimized command substitution.
Change the criterion for builtins to be safe to execute in the same process
in optimized command substitution from a blacklist of only cd, . and eval to
a whitelist.

This avoids clobbering the main shell environment such as by $(exit 4) and
$(set -x).

The builtins jobid, jobs, times and trap can still show information not
available in a child process; this is deliberately permitted. (Changing
traps is not.)

For some builtins, whether they are safe depends on the arguments passed to
them. Some of these are always considered unsafe to keep things simple; this
only harms efficiency a little in the rare case they are used alone in a
command substitution.
2010-12-30 22:33:55 +00:00
Jilles Tjoelker
b0aecb3d03 sh: Add two tests for special cases in command substitution that already
work in stable/8.
2010-12-30 15:04:59 +00:00
Jilles Tjoelker
acd7984f96 sh: Don't do optimized command substitution if expansions have side effects.
Before considering to execute a command substitution in the same process,
check if any of the expansions may have a side effect; if so, execute it in
a new process just like happens if it is not a single simple command.

Although the check happens at run time, it is a static check that does not
depend on current state. It is triggered by:
- expanding $! (which may cause the job to be remembered)
- ${var=value} default value assignment
- assignment operators in arithmetic
- parameter substitutions in arithmetic except ${#param}, $$, $# and $?
- command substitutions in arithmetic

This means that $((v+1)) does not prevent optimized command substitution,
whereas $(($v+1)) does, because $v might expand to something containing
assignment operators.

Scripts should not depend on these exact details for correctness. It is also
imaginable to have the shell fork if and when a side effect is encountered
or to create a new temporary namespace for variables.

Due to the $! change, the construct $(jobs $!) no longer works. The value of
$! should be stored in a variable outside command substitution first.
2010-12-28 21:27:08 +00:00
Jilles Tjoelker
f3c2011efb sh: Add test for optimized command substitution.
This test verifies that certain expansions without side effects do not
cause the command substitution to be executed in a child process.

This is not a correctness requirement, but it involves a nontrivial amount
of code and it would be unfortunate if it stopped working.
2010-12-28 14:58:08 +00:00
Jilles Tjoelker
45b71cd16e sh: Make expansion errors in optimized command substitution non-fatal.
Command substitutions consisting of a single simple command are executed in
the main shell process but this should be invisible apart from performance
and very few exceptions such as $(trap).
2010-12-28 13:28:24 +00:00
Jilles Tjoelker
a355eb9e1a sh: Add a testcase for cmdsubst errors that already works properly.
If a command substitution consists of one special builtin and there is a
redirection error, this should not abort the outer shell.
It was fixed in r201366 by ignoring special builtin properties for command
substitutions consisting of one builtin.
2010-12-27 23:56:03 +00:00
Ed Maste
f8e809686a Restore two commented-out tests from plus-minus1.0 to a new file.
These two cases pass on -CURRENT but fail on stable/8.

Reviewed by:	jilles
2010-12-27 15:57:41 +00:00
Ed Maste
65db095da0 Remove commented-out test that's covered in plus-minus2.0 anyway.
Discussed with: jilles
2010-12-26 23:19:16 +00:00
Jilles Tjoelker
6a6760db7f sh: Make warnings in the printf builtin non-fatal, like in the program.
The #define for warnx now behaves much like the libc function (except that
it uses sh command name and output).

Also, it now uses C99 __VA_ARGS__ so there is no need for three different
macros for 0, 1 or 2 parameters.
2010-12-20 23:06:57 +00:00
Jilles Tjoelker
79357531c8 sh: arith: Disallow decimal constants starting with 0 (containing 8 or 9).
Constants in arithmetic starting with 0 should be octal only.

This avoids the following highly puzzling result:
  $ echo $((018-017))
  3
by making it an error instead.
2010-12-18 23:03:51 +00:00
Jilles Tjoelker
fa0951d63a sh: Fix corruption of command substitutions with special chars after newline
The CTLESC byte to protect a special character was output before instead of
after a newline directly preceding the special character.

The special handling of newlines is because command substitutions discard
all trailing newlines.
2010-12-16 23:28:20 +00:00
Jilles Tjoelker
2a3de776bf sh: Fix some tests that used sh instead of ${SH}
so they tested the wrong sh.

This was caused because these tests were committed after the sh -> ${SH}
change but were created before.
2010-12-12 21:18:16 +00:00
Jilles Tjoelker
63f6e7ba56 sh: Add a test for r216387 (long arithmetic expression in here document). 2010-12-12 16:56:16 +00:00
Jilles Tjoelker
95787f5dc0 sh: Make the test for cd/pwd with long pathnames more useful:
* Use $(getconf PATH_MAX /) to make sure we actually exercise the hard part
* Delete our test area even if the test fails
2010-11-28 22:49:58 +00:00
Jilles Tjoelker
4fadeef03f sh: Add a test that manipulates various long strings.
It is quite effective at detecting mistakes in memalloc.c and code using it.

It is somewhat slow, but some of the patches in my queue improve it.
2010-11-19 22:25:32 +00:00
Jilles Tjoelker
440bbebcc9 sh: Add another simple test for the wait builtin. 2010-11-19 21:15:06 +00:00
Jilles Tjoelker
47fdf870a7 test: Move tests to tools/regression/bin/test.
Convert the tests to the perl prove format.
Remove obsolete TEST.README (results of an old TEST.sh for some old Unices)
and TEST.csh (old tests without correct values, far less complete than
TEST.sh).

MFC after:	1 week
2010-11-08 23:15:10 +00:00
Jilles Tjoelker
5aa39e6a7e sh: Add simple tests for printf.
These are not meant as a replacement for tools/regression/usr.bin/printf/*
but to detect errors specific to making it a shell builtin.
2010-11-05 21:47:58 +00:00
Jilles Tjoelker
135ff4b5b0 sh: Fix some issues with aliases and case, by importing dash checkkwd code.
This moves the function of the noaliases variable into the checkkwd
variable. This way it is properly reset on errors and aliases can be used
normally in the commands for each case (the case labels recognize the
keyword esac but no aliases).

The new code is clearer as well.

Obtained from:	dash
2010-11-02 23:44:29 +00:00
Jilles Tjoelker
e20776d503 sh: Detect various additional errors in the parser.
Apart from detecting breakage earlier or at all, this also fixes a segfault
in the testsuite. The "handling" of the breakage left an invalid internal
representation in some cases.

Examples:
  echo a; do echo b
  echo `) echo a`
  echo `date; do do do`

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-29 21:06:57 +00:00
Jilles Tjoelker
60f7eec450 sh: Fix some issues with CTL* bytes and ${var#pat}.
subevalvar() incorrectly assumed that CTLESC bytes were present iff the
expansion was quoted. However, they are present iff various processing such
as word splitting is to be done later on.

Example:
  v=@$e@$e@$e@
  y="${v##*"$e"}"
  echo "$y"
failed if $e contained the magic CTLESC byte.

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-29 19:34:57 +00:00
Jilles Tjoelker
048f26671a sh: Do IFS splitting on word in ${v+word} and ${v-word}.
The code is inspired by NetBSD sh somewhat, but different because we
preserve the old Almquist/Bourne/Korn ability to have an unquoted part in a
quoted ${v+word}. For example, "${v-"*"}" expands to $v as a single field if
v is set, but generates filenames otherwise.

Note that this is the only place where we split text literally from the
script (the similar ${v=word} assigns to v and then expands $v). The parser
must now add additional markers to allow the expansion code to know whether
arbitrary characters in substitutions are quoted.

Example:
  for i in ${$+a b c}; do echo $i; done

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-29 13:42:18 +00:00
Jilles Tjoelker
6c38071288 sh: Only accept a '}' inside ${v+-=?...} if double-quote state matches.
If double-quote state does not match, treat the '}' literally.

This ensures double-quote state remains the same before and after a
${v+-=?...} which helps with expand.c.

It makes things like
  ${foo+"\${bar}"}
which I have seen in the wild work as expected.

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-28 22:34:49 +00:00
Jilles Tjoelker
9cec947f3f sh: Make double-quotes quote a '}' inside ${v#...} and ${v%...}.
Exp-run done by:	pav (with some other sh(1) changes)
PR:			bin/57554
2010-10-28 21:51:14 +00:00
Jilles Tjoelker
67e109adbe sh: Do not allow overriding a special builtin with a function.
This is a syntax error.

POSIX does not say explicitly whether defining a function with the same name
as a special builtin is allowed, but it does say that it is impossible to
call such a function.

A special builtin can still be overridden with an alias.

This commit is part of a set of changes that will ensure that when
something looks like a special builtin to the parser, it is one. (Not the
other way around, as it remains possible to call a special builtin named
by a variable or other substitution.)

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-24 22:03:21 +00:00
Jilles Tjoelker
074e83b14e sh: Make sure defined functions can actually be called.
Add some conservative checks on function names:
- Disallow expansions or quoting characters; these can only be called via
  strange control characters
- Disallow '/'; these functions cannot be called anyway, as exec.c assumes
  they are pathnames
- Make the CTL* bytes work properly in function names.

These are syntax errors.

POSIX does not require us to support more than names (letters, digits and
underscores, not starting with a digit), but I do not want to restrict it
that much at this time.

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-24 20:45:13 +00:00
Jilles Tjoelker
3dec7d0c15 sh: Check whether dup2 was successful for >&FD and <&FD.
A failure (usually caused by FD not being open) is a redirection error.

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-24 20:09:49 +00:00
Jilles Tjoelker
7aaae32724 sh: Add a test trying to close a descriptor that is not open.
In stable/8 and older, this fails. Some of the redirection changes in head
have fixed it.
2010-10-24 19:56:34 +00:00
Jilles Tjoelker
ba08f69b5c sh: Change ! within a pipeline to start a new pipeline instead.
This is how ksh93 treats ! within a pipeline and makes the ! in
  a | ! b | c
negate the exit status of the pipeline, as if it were
  a | { ! b | c; }

Side effect: something like
  f() ! a
is now a syntax error, because a function definition takes a command,
not a pipeline.

Exp-run done by:	pav (with some other sh(1) changes)
2010-10-24 17:06:49 +00:00
Jilles Tjoelker
281fb05e83 sh: Add some testcases for alias expansion. 2010-10-24 16:55:17 +00:00
Jilles Tjoelker
f1bb5f6a87 sh: Allow running 'prove' from tools/regression/bin/sh again
without needing to set special environment variables, testing the 'sh' from
PATH.
2010-10-15 20:01:35 +00:00
David E. O'Brien
7c7a210ab8 Embellish this testcase a little bit to be more clear what the output is
and why.  The first case is correct usage which has but one correct output.
The 2nd and 3rd cases are incorrect usage in which the exact output is
not standardized and various shells give various allowable output.
2010-10-14 23:28:31 +00:00
David E. O'Brien
7cfe69417c Do not assume in growstackstr() that a "precious" character will be
immediately written into the stack after the call.  Instead let the caller
manage the "space left".

Previously, growstackstr()'s assumption causes problems with STACKSTRNUL()
where we want to be able to turn a stack into a C string, and later
pretend the NUL is not there.

This fixes a bug in STACKSTRNUL() (that grew the stack) where:
1. STADJUST() called after a STACKSTRNUL() results in an improper adjust.
   This can be seen in ${var%pattern} and ${var%%pattern} evaluation.
2. Memory leak in STPUTC() called after a STACKSTRNUL().

Reviewed by:	jilles
2010-10-13 23:29:09 +00:00
David E. O'Brien
f3bf9b7a16 Allow one to regression test 'sh' changes without having to install
a potentially bad /bin/sh first.
2010-10-12 18:20:38 +00:00
David E. O'Brien
5f7f699749 Correct regression test to not show a false positive when run as root. 2010-10-11 23:24:57 +00:00
Jilles Tjoelker
8f2dc7de67 sh: Fix exit status if return is used within a loop condition. 2010-09-11 15:07:40 +00:00
Jilles Tjoelker
011d162dd3 sh: Apply variable assignments left-to-right in bltinlookup().
Example:
  HOME=foo HOME=bar cd
2010-09-11 14:15:50 +00:00
Jilles Tjoelker
917fdfb106 sh: Fix 'read' if all chars before the first IFS char are backslash-escaped.
Backslash-escaped characters did not set the flag for a non-IFS character.

MFC after:	2 weeks
2010-09-08 20:35:43 +00:00
Jilles Tjoelker
ad931dfdcb sh: Add simple tests for backslashes in the read builtin. 2010-09-08 18:32:23 +00:00
Jilles Tjoelker
10ea2923a9 sh: Add a test that 'read' leaves the file pointer at the correct place.
Naive buffering would break the common while read x... construct, which did
not appear to be tested yet.
2010-09-03 21:17:33 +00:00
Jilles Tjoelker
83866607fb sh: Weaken builtins/command4 test to only require a nonzero exit status.
This matches what is in POSIX; various other shells use different exit
statuses.

Note that it is still required that there be no output.
2010-08-29 20:53:24 +00:00
Brian Somers
25fdbebeb2 Add a Makefile for tools/regression/bin and support 'all' in
pax/Makefile.

MFC after:	3 weeks
2010-08-29 12:14:53 +00:00
Brian Somers
cd14b45756 Correct an out-by-one error when earlying out ustar filenames that
are too long.  Filenames escaping this test are caught later on,
so the bug doesn't cause any breakage.

Document the correct ustar limitations in pax.  As I have no access
to the IEEE 1003.2 spec, I can only assume that the limitations
imposed are in fact correct.

Add regression tests for the filename limitations imposed by pax.

MFC after:	3 weeks
2010-08-29 11:56:56 +00:00
Jilles Tjoelker
8fdbdb5d50 sh: Remove remnants of '!!' to negate pattern.
This Almquist extension was disabled long ago.

In pathname generation, components starting with '!!' were treated as
containing wildcards, causing unnecessary readdir (which could fail, causing
pathname generation to fail while it should not).
2010-08-22 21:18:21 +00:00
Jilles Tjoelker
394357b2b6 sh: Test that all bytes from 128 to 255 can be used in IFS.
To avoid multibyte issues, this test forces ISO8859-1 charset.

This also passes on stable/8.
2010-08-22 13:09:12 +00:00
Jilles Tjoelker
193da04bd8 sh: Add a test for breaking from a loop outside the current function.
It is unwise to rely on this but I'd like to know if this would break.
2010-08-22 11:04:30 +00:00
Jilles Tjoelker
44510b41ff sh: Add a test for break from a trap action. 2010-08-18 20:26:50 +00:00
Jilles Tjoelker
7ba25e6e69 sh: Reduce unnecessary testsuite failures with other shells. 2010-08-16 22:23:19 +00:00
Jilles Tjoelker
2070b57f64 sh: Split off a more dubious test from parser/heredoc2.0. 2010-08-16 21:14:49 +00:00