| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
|
| |
Path generation was not according to collate
Approved by: jilles
|
|
|
|
| |
Found by: clang static analyzer
|
|
|
|
|
|
|
| |
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'.
|
| |
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
"$@" should expand to no words if there are no positional parameters, but
""$@ should always expand to at least an empty word.
|
|
|
|
|
| |
Add dummy entries before and after so arglist's array is directly usable as
argv.
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
| |
* Remove some gotos.
* Remove unused parameter.
* Remove duplicate code.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
|
|
| |
Quoting during expansion only cares about CCTL, which is the same for
DQSYNTAX and SQSYNTAX.
|
|
|
|
|
|
|
| |
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
|
|
|
|
| |
This makes a difference if IFS starts with *, ?, [ or a CTL* byte.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
Leading zeroes were ignored when checking whether a positional parameter is
set, but not when expanding its value. Ignore leading zeroes in any case.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
Example:
f() { : ${LINENO+$((1/0))}; }
and call this function twice.
|
| |
|
| |
|
|
|
|
|
|
|
| |
It now passes WARNS=7 with clang on i386.
GCC 4.2.1 does not understand setjmp() properly so will always trigger
-Wuninitialized. I will not add the volatile keywords to suppress this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Expand here documents at the same point other redirections are expanded but
use a non-fork subshell environment (like simple command substitutions) for
compatibility. Substitition errors result in an empty here document like
before.
As a result, a fork is avoided for short (<4K) expanded here documents.
Unexpanded here documents (with quoted end marker after <<) are not affected
by this change. They already only forked when >4K.
Side effects:
* Order of expansion is slightly different.
* Slow expansions are not executed in parallel with the redirected command.
* A non-fork subshell environment is subtly different from a forked process.
|
| |
|
| |
|
|
|
|
|
|
| |
This improves performance for globs where a slash or another component
follows a component with metacharacters by eliminating unnecessary attempts
to open directories that are not.
|
| |
|
|
|
|
|
| |
Example:
case x in [[:alpha:]]) echo yes ;; esac
|
|
|
|
|
|
| |
Have mkbuiltins write the prototypes for the *cmd functions to builtins.h
instead of builtins.c and include builtins.h in more .c files instead of
duplicating prototypes for *cmd functions in other headers.
|
|
|
|
|
|
|
|
|
|
|
| |
In optimized command substitution, save and restore any variables changed by
expansions (${var=value} and $((var=assigned))), instead of trying to
determine if an expansion may cause such changes.
If $! is referenced in optimized command substitution, do not cause jobs to
be remembered longer.
This fixes $(jobs $!) again, simplifies the man page and shortens the code.
|
|
|
|
|
|
|
|
| |
When I added UTF-8 support in r221646, the LC_COLLATE-based ordering broke
because of sign extension of char.
Because of libc restrictions, this does not work for UTF-8. For UTF-8
locales, ranges always use character code order.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The function name expandstr() and the general idea of doing this kind of
expansion by treating the text as a here document without end marker is from
dash.
All variants of parameter expansion and arithmetic expansion also work (the
latter is not required by POSIX but it does not take extra code and many
other shells also allow it).
Command substitution is prevented because I think it causes too much code to
be re-entered (for example creating an unbounded recursion of trace lines).
Unfortunately, our LINENO is somewhat crude, otherwise PS4='$LINENO+ ' would
be quite useful.
|
|
|
|
|
|
| |
If IFS is null, unquoted $@/$* should still expand to separate words.
This differs from quoted $@ (which does not depend on IFS) in that pathname
generation is performed and empty words are removed.
|
|
|
|
|
|
|
|
|
|
| |
?, [...] patterns match codepoints instead of bytes. They do not match
invalid sequences. [...] patterns must not contain invalid sequences
otherwise they will not match anything. This is so that ${var#?} removes the
first codepoint, not the first byte, without putting UTF-8 knowledge into
the ${var#pattern} code. However, * continues to match any string and an
invalid sequence matches an identical invalid sequence. (This differs from
fnmatch(3).)
|
|
|
|
|
| |
If the current locale uses UTF-8, ${#var} counts codepoints (more precisely,
bytes b with (b & 0xc0) != 0x80).
|