summaryrefslogtreecommitdiffstats
path: root/bin/sh/expand.c
Commit message (Collapse)AuthorAgeFilesLines
* MFC r315005: sh: Fix executing wrong command with ${x#$(y)}$(z).jilles2017-03-181-1/+3
| | | | | | | | | | | | | | | | 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 r314686: sh: Fix crash if a -T trap is taken during command substitutionjilles2017-03-121-2/+5
| | | | | | | | | | | | | | | 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 r302937ache2016-08-181-1/+1
| | | | | | Path generation was not according to collate Approved by: jilles
* sh: Fix some dead stores.jilles2016-03-061-2/+1
| | | | Found by: clang static analyzer
* sh: Constify internal representation in expand.c.jilles2016-01-241-22/+28
| | | | | | | 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'.
* sh: Reduce size of options table.jilles2016-01-071-2/+2
|
* sh: Remove redundant CTLQUOTEMARK checks.jilles2015-12-311-18/+2
| | | | | | | | 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).
* sh: Reindent expandmeta().jilles2015-12-311-21/+21
|
* sh: Perform pathname generation during the first expansion phases.jilles2015-12-311-51/+53
| | | | | | | | 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.
* sh: Perform IFS splitting during the first expansion phases.jilles2015-12-311-362/+253
| | | | | | | | | 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.
* sh: Split subevalvar() in #/##/%/%% and =/? parts.jilles2015-12-291-28/+45
|
* sh: Fix ""$@, which should not use the special case for "$@".jilles2015-11-181-1/+2
| | | | | "$@" should expand to no words if there are no positional parameters, but ""$@ should always expand to at least an empty word.
* sh: Avoid copying argv for simple commands.jilles2015-11-011-2/+1
| | | | | Add dummy entries before and after so arglist's array is directly usable as argv.
* sh: Make struct arglist an array instead of a linked list.jilles2015-10-111-141/+74
| | | | | | | | | | | 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.
* wordexp: Rewrite to make WRDE_NOCMD reliable.jilles2015-09-301-0/+54
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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)
* sh: Add set -o nolog.jilles2015-08-291-1/+1
| | | | | | | | | | 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.
* sh: Fix out of bounds read when there is no ] after a [:class:].jilles2015-08-251-12/+7
| | | | | | | | | | | 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
* Fix unitialized variable that broke sh on PowerPC starting with r278826.nwhitehorn2015-02-261-1/+1
|
* sh: Various cleanups to expand.c:jilles2015-02-151-60/+55
| | | | | | * Remove some gotos. * Remove unused parameter. * Remove duplicate code.
* sh: Prefer "" to nullstr where possible.jilles2015-02-151-2/+1
|
* sh: Add stsavestr(), like savestr() but allocates using stalloc().jilles2015-02-151-4/+1
|
* sh: Remove EXP_REDIR.jilles2014-12-211-12/+6
| | | | | | | | | | 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
* sh: Use DQSYNTAX only while expanding, not SQSYNTAX.jilles2014-11-221-1/+1
| | | | | Quoting during expansion only cares about CCTL, which is the same for DQSYNTAX and SQSYNTAX.
* sh: Fix corruption of CTL* bytes in positional parameters in redirection.jilles2014-10-311-1/+1
| | | | | | | 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
* Treat IFS separators in "$*" as quoted.jilles2014-10-281-5/+8
| | | | This makes a difference if IFS starts with *, ?, [ or a CTL* byte.
* sh: Remove more gotos.jilles2014-10-151-23/+21
|
* sh: Eliminate some gotos.jilles2014-10-051-10/+5
|
* sh: Correctly handle positional parameters beyond INT_MAX on 64-bit systems.jilles2014-07-121-2/+4
| | | | | | | | | | | | | 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.
* sh: Consistently treat ${01} like $1.jilles2014-07-121-7/+6
| | | | | Leading zeroes were ignored when checking whether a positional parameter is set, but not when expanding its value. Ignore leading zeroes in any case.
* sh: Fix possible memory leaks and double frees with unexpected SIGINT.jilles2014-03-261-0/+3
|
* sh: Add some consts.jilles2014-03-141-5/+5
|
* sh: Make argstr() return where it stopped and simplify expari() using this.jilles2014-03-041-21/+5
|
* sh: Simplify expari().jilles2014-03-021-48/+46
| | | | | | | | | 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.
* sh: Do not corrupt internal representation if LINENO inner expansion fails.jilles2014-02-271-6/+6
| | | | | | Example: f() { : ${LINENO+$((1/0))}; } and call this function twice.
* sh: Make expari() static.jilles2014-02-261-1/+2
|
* sh: Prefer memcpy() to strcpy() in most cases. Remove the scopy macro.jilles2013-11-301-2/+4
|
* sh: Fix various compiler warnings.jilles2013-04-011-6/+7
| | | | | | | 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.
* sh: Expand here documents in the current process.jilles2013-02-031-13/+0
| | | | | | | | | | | | | | | | | 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.
* sh: Make various functions static.jilles2012-01-011-1/+2
|
* sh: Make patmatch() non-recursive.jilles2012-01-011-37/+58
|
* sh: Use dirent.d_type in pathname generation.jilles2011-12-281-0/+4
| | | | | | 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.
* sh: Cache de->d_namlen in a local variable.jilles2011-12-281-6/+8
|
* sh: Add support for named character classes in bracket expressions.jilles2011-06-151-1/+37
| | | | | Example: case x in [[:alpha:]]) echo yes ;; esac
* sh: Fix duplicate prototypes for builtins.jilles2011-06-131-0/+1
| | | | | | 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.
* sh: Save/restore changed variables in optimized command substitution.jilles2011-06-121-72/+0
| | | | | | | | | | | 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.
* sh: Fix locale-dependent ranges in bracket expressions.jilles2011-06-121-4/+4
| | | | | | | | 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.
* sh: Do parameter expansion before printing PS4 (set -x).jilles2011-06-091-0/+1
| | | | | | | | | | | | | | | | 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.
* sh: Fix unquoted $@/$* if IFS=''.jilles2011-05-271-2/+5
| | | | | | 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.
* sh: Add UTF-8 support to pattern matching.jilles2011-05-081-12/+50
| | | | | | | | | | ?, [...] 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).)
* sh: Add UTF-8 support to ${#var}.jilles2011-05-071-3/+13
| | | | | If the current locale uses UTF-8, ${#var} counts codepoints (more precisely, bytes b with (b & 0xc0) != 0x80).
OpenPOWER on IntegriCloud