Commit Graph

150 Commits

Author SHA1 Message Date
Jilles Tjoelker
468ed39612 sh: Fix ${param?} default error message
If word in ${param?word} is missing, the shell shall write a default error
message. So expanding ${param?} when param is not set should write an error
message like

sh: param: parameter not set

This was broken by r316417.

PR:		233585
2018-11-28 20:03:53 +00:00
Jilles Tjoelker
4269bba2eb sh: Fix formal overflow in pointer arithmetic
The intention is to lower the value of the pointer, which according to ubsan
cannot be done by adding an unsigned quantity.

Reported by:	kevans
Approved by:	re (kib)
MFC after:	1 week
2018-09-05 19:16:09 +00:00
Jilles Tjoelker
4d7f36eea5 sh: Don't have [ match any [[:class:]]
Submitted by:	Robert Elz
MFC after:	3 days
2018-04-29 17:46:08 +00:00
Jilles Tjoelker
1b21b7fa89 sh: Fix '-' from quoted arithmetic in case/glob pattern range.
It does not make much sense to generate the '-' in a pattern bracket
expression using arithmetic expansion, but it does not make sense to forbid
it either.

Try to avoid reprocessing the string if it is unnecessary.
2017-05-14 13:14:19 +00:00
Jilles Tjoelker
b98072777f sh: Update TOUR and comments for some code changes, some of them old.
Also, improve some terminology in TOUR and comments.
2017-05-06 13:28:42 +00:00
Jilles Tjoelker
d4993b6db2 sh: Simplify handling of newlines in command substitution.
Unless we need to split on newlines, just append them as normal and remove
them at the end.
2017-04-28 16:16:22 +00:00
Jilles Tjoelker
c39d3320ab sh: Remove global state from collate_range_cmp().
The global state is not used across invocations of collate_range_cmp().
2017-04-02 14:02:10 +00:00
Jilles Tjoelker
e59833ccfe sh: Don't scan word twice in ${param=word}. 2017-04-02 13:43:45 +00:00
Jilles Tjoelker
e2708b1624 sh: Don't scan word twice in ${param#%##%%word}.
If word is expanded, use the found end instead of iterating over the data
again.
2017-04-02 13:29:27 +00:00
Jilles Tjoelker
9e1bb30e23 sh: Don't scan word twice in ${param+-word}.
There is no longer a case where argbackq has already been advanced but the
string pointer needs to be advanced.
2017-04-02 12:37:43 +00:00
Jilles Tjoelker
a54caffda0 sh: Fix build with -DDEBUG=2.
With the new expansion code (word splitting during instead of after other
expansion processing), tracing the result of command substitution is no
longer possible, so stop trying.
2017-03-19 21:18:53 +00:00
Jilles Tjoelker
56bf1d616f sh: Remove unused return value of subevalvar_misc(). 2017-03-18 16:09:30 +00:00
Jilles Tjoelker
439948cdf6 sh: Get rid of global variable argbackq. 2017-03-16 21:53:55 +00:00
Jilles Tjoelker
8999a290ab sh: Fix executing wrong command with ${unsetvar#$(cmdsubst)}$(cmdsubst).
The parsed internal representation of words consists of a byte string with a
list of nodes (commands in command substitution). Each unescaped CTLBACKQ or
CTLBACKQ | CTLQUOTE byte corresponds to an entry in the list.

If param in ${param#%##%%word} is not set, the word is not expanded (in a
deviation of POSIX shared with other ash variants and ksh93). Erroneously,
the pointer in the list of commands (argbackq) was not advanced. This caused
the wrong command to be executed later if the outer word contained another
command substitution.

Example:
  echo "${unsetvar#$(echo a)}$(echo b)"
wrote "a" but should write "b".

MFC after:	1 week
2017-03-10 16:04:00 +00:00
Jilles Tjoelker
586fd24857 sh: Fix crash if a -T trap is taken during command substitution.
Code like  t=$(stat -f %m "$file")  segfaulted if -T was active and a trap
was taken while the shell was waiting for the child process to finish.

What happened was that the dotrap() call in waitforjob() was hit. This
re-entered command execution (including expand.c) at a point not expected by
expbackq(), and global state (unallocated stack string and argbackq) was
corrupted.

To fix this, change expbackq() to prepare for command execution to be
re-entered.

Reported by:	bdrewery
MFC after:	1 week
2017-03-04 22:58:34 +00:00
Warner Losh
fbbd9655e5 Renumber copyright clause 4
Renumber cluase 4 to 3, per what everybody else did when BSD granted
them permission to remove clause 3. My insistance on keeping the same
numbering for legal reasons is too pedantic, so give up on that point.

Submitted by:	Jan Schaumann <jschauma@stevens.edu>
Pull Request:	https://github.com/freebsd/freebsd/pull/96
2017-02-28 23:42:47 +00:00
Jilles Tjoelker
3bb6ada261 sh: Fix a clang warning.
Submitted by:	bdrewery
2016-07-31 13:11:34 +00:00
Andrey A. Chernov
143d321a30 Path generation was not according to collate
Approved by:    jilles
2016-07-16 13:26:18 +00:00
Andrey A. Chernov
fa93fc659f Back out non-collating [a-z] ranges.
Instead of changing the whole course to another POSIX-permitted way
for consistency and uniformity I decide to completely ignore missing
regex fucntionality and focus on fixing bugs in what we have now,
too many small obstacles we have choicing other way, counting ports.
Corresponding libc changes are backed out in r302824.
2016-07-14 09:34:42 +00:00
Andrey A. Chernov
3ea37deb6c After removing collation for [a-z] ranges in r302512, do it here too.
Approved by:    jilles
2016-07-13 08:13:09 +00:00
Jilles Tjoelker
acb4eada18 sh: Fix some dead stores.
Found by:	clang static analyzer
2016-03-06 17:24:02 +00:00
Jilles Tjoelker
52d5897d50 sh: Constify internal representation in expand.c.
Forbid (temporary or permanent) modifications of the strings in NARG nodes
during expansion.

Tilde expansion now needs to copy the username for the terminating '\0'.
2016-01-24 22:26:25 +00:00
Jilles Tjoelker
3da40d4a6b sh: Reduce size of options table. 2016-01-07 23:13:20 +00:00
Jilles Tjoelker
bc57b4d469 sh: Remove redundant CTLQUOTEMARK checks.
With the new expand.c code, the intermediate representation passed to the
pathname generation code only contains CTLESC, not CTLQUOTEMARK.

CTLQUOTEMARK now only occurs in the text of NARG nodes (output of the
parser).
2015-12-31 20:15:57 +00:00
Jilles Tjoelker
ee97d8648c sh: Reindent expandmeta(). 2015-12-31 18:56:11 +00:00
Jilles Tjoelker
0e39c931e2 sh: Perform pathname generation during the first expansion phases.
This avoids the need to add and remove CTLESC bytes if pathname generation
will not be performed (set -f).

Side effect: the order of operations is slightly different: pathname
generation in ${$+* $(CMD)} will not see filesystem changes from CMD.
2015-12-31 18:47:54 +00:00
Jilles Tjoelker
47d8814c7f sh: Perform IFS splitting during the first expansion phases.
This simplifies the code and should be faster in some cases.

Side effect: the order of operations is different so that the value of IFS
used when IFS is modified during expansion (${IFS:=...}, ${IFS=...} or
$((...IFS=...))) may be different. Note that this order is highly unportable
between shells.
2015-12-31 17:51:15 +00:00
Jilles Tjoelker
4f2f5faa62 sh: Split subevalvar() in #/##/%/%% and =/? parts. 2015-12-29 20:51:29 +00:00
Jilles Tjoelker
a5cb58abc8 sh: Fix ""$@, which should not use the special case for "$@".
"$@" should expand to no words if there are no positional parameters, but
""$@ should always expand to at least an empty word.
2015-11-18 21:09:03 +00:00
Jilles Tjoelker
046bfe5240 sh: Avoid copying argv for simple commands.
Add dummy entries before and after so arglist's array is directly usable as
argv.
2015-11-01 22:07:40 +00:00
Jilles Tjoelker
8ef0ae8a8f sh: Make struct arglist an array instead of a linked list.
This simplifies the code (e.g. allowing use of qsort(3) instead of a
hand-rolled mergesort) and should have better cache properties.

The waste of unused args arrays after resizes is approximately the same as
the savings from getting rid of the next pointers.

At the same time, remove a piece of global state and move some duplicated
code into a function.
2015-10-11 21:33:00 +00:00
Jilles Tjoelker
d358fa780b wordexp: Rewrite to make WRDE_NOCMD reliable.
Shell syntax is too complicated to detect command substitution and unquoted
operators reliably without implementing much of sh's parser. Therefore, have
sh do this detection.

While changing sh's support anyway, also read input from a pipe instead of
arguments to avoid {ARG_MAX} limits and improve privacy, and output count
and length using 16 instead of 8 digits.

The basic concept is:
execl("/bin/sh", "sh", "-c", "freebsd_wordexp ${1:+\"$1\"} -f "$2",
    "", flags & WRDE_NOCMD ? "-p" : "", <pipe with words>);

The WRDE_BADCHAR error is still implemented in libc. POSIX requires us to
fail strings containing unquoted braces with code WRDE_BADCHAR. Since this
is normally not a syntax error in sh, there is still a need for checking
code in libc, we_check().

The new we_check() is an optimistic check that all the characters
  <newline> | & ; < > ( ) { }
are quoted. To avoid duplicating too much sh logic, such characters are
permitted when quoting characters are seen, even if the quoting characters
may themselves be quoted. This code reports all WRDE_BADCHAR errors; bad
characters that get past it and are a syntax error in sh return WRDE_SYNTAX.

Although many implementations of WRDE_NOCMD erroneously allow some command
substitutions (and ours even documented this), there appears to be code that
relies on its security (codesearch.debian.net shows quite a few uses).
Passing untrusted data to wordexp() still exposes a denial of service
possibility and a fairly large attack surface.

Reviewed by:	wblock (man page only)
MFC after:	2 weeks
Relnotes:	yes
Security:	fixes command execution with wordexp(untrusted, WRDE_NOCMD)
2015-09-30 21:32:29 +00:00
Jilles Tjoelker
62c3711632 sh: Add set -o nolog.
POSIX requires this to prevent entering function definitions in history but
this implementation does nothing except retain the option's value. In ksh88,
function definitions were usually entered in the history file, even when
they came from ~/.profile and the $ENV file, to allow displaying their
definitions.

This is also the first option that does not have a letter.
2015-08-29 19:41:47 +00:00
Jilles Tjoelker
4a4867d667 sh: Fix out of bounds read when there is no ] after a [:class:].
The initial check for a matching ] was incorrect if a ] may be consumed by a
[:class:]. The subsequent loop assumed that there must be a ].

Remove the initial check and make the loop cope with a missing ].

Found with afl-fuzz.

MFC after:	1 week
2015-08-25 21:55:15 +00:00
Nathan Whitehorn
c4b725f42a Fix unitialized variable that broke sh on PowerPC starting with r278826. 2015-02-26 20:59:18 +00:00
Jilles Tjoelker
7034d8df04 sh: Various cleanups to expand.c:
* Remove some gotos.
* Remove unused parameter.
* Remove duplicate code.
2015-02-15 22:38:00 +00:00
Jilles Tjoelker
781bfb5a53 sh: Prefer "" to nullstr where possible. 2015-02-15 21:47:43 +00:00
Jilles Tjoelker
a4652c280b sh: Add stsavestr(), like savestr() but allocates using stalloc(). 2015-02-15 21:41:29 +00:00
Jilles Tjoelker
f649ab8b15 sh: Remove EXP_REDIR.
EXP_REDIR was supposed to generate pathnames in redirection if exactly one
file matches, as permitted but not required by POSIX in interactive mode. It
is unlikely this will be implemented.

No functional change is intended.

MFC after:	1 week
2014-12-21 22:18:30 +00:00
Jilles Tjoelker
08dc8cf90c sh: Use DQSYNTAX only while expanding, not SQSYNTAX.
Quoting during expansion only cares about CCTL, which is the same for
DQSYNTAX and SQSYNTAX.
2014-11-22 16:03:18 +00:00
Jilles Tjoelker
5dff1efc27 sh: Fix corruption of CTL* bytes in positional parameters in redirection.
EXP_REDIR was not being checked for while expanding positional parameters in
redirection, so CTL* bytes were not being prefixed where they should be.

MFC after:	1 week
2014-10-31 22:28:10 +00:00
Jilles Tjoelker
3fb51b3a43 Treat IFS separators in "$*" as quoted.
This makes a difference if IFS starts with *, ?, [ or a CTL* byte.
2014-10-28 22:14:31 +00:00
Jilles Tjoelker
622fdf3236 sh: Remove more gotos. 2014-10-15 21:20:56 +00:00
Jilles Tjoelker
33c5acf038 sh: Eliminate some gotos. 2014-10-05 21:51:36 +00:00
Jilles Tjoelker
7b9104c0a9 sh: Correctly handle positional parameters beyond INT_MAX on 64-bit systems.
Currently, there can be no more than INT_MAX positional parameters. Make
sure to treat all higher ones as unset to avoid incorrect results and
crashes.

On 64-bit systems, our atoi() takes the low 32 bits of the strtol() and
sign-extends them.

On 32-bit systems, the call to atoi() returned INT_MAX for too high values
and there is not enough address space for so many positional parameters, so
there was no issue.
2014-07-12 21:54:11 +00:00
Jilles Tjoelker
5ddabb8348 sh: Consistently treat ${01} like $1.
Leading zeroes were ignored when checking whether a positional parameter is
set, but not when expanding its value. Ignore leading zeroes in any case.
2014-07-12 10:27:30 +00:00
Jilles Tjoelker
1632bf1a88 sh: Fix possible memory leaks and double frees with unexpected SIGINT. 2014-03-26 20:43:40 +00:00
Jilles Tjoelker
61346cbdc7 sh: Add some consts. 2014-03-14 21:45:37 +00:00
Jilles Tjoelker
a2cba42fc2 sh: Make argstr() return where it stopped and simplify expari() using this. 2014-03-04 22:30:38 +00:00
Jilles Tjoelker
ce16da82dd sh: Simplify expari().
Redo expari() like evalvar(). This makes the logic more understandable and
avoids possible problems if arithmetic expansion occurs if CTLESC characters
are not generated (looking backwards for CTLARI is not generally possible in
that case but the old code tried anyway).

This adds an extra argstr() recursion.
2014-03-02 22:59:34 +00:00