Re: use-after-free in read_token_word

2023-03-15 Thread Grisha Levit
Also in parse_matched_pair:

diff --git a/parse.y b/parse.y
index 0a8c039a..1001ac1b 100644
--- a/parse.y
+++ b/parse.y
@@ -3906,14 +3906,13 @@ parse_matched_pair (int qc, int open, int
close, size_t *lenp, int flags)
/* Locale expand $"..." here. */
/* PST_NOEXPAND */
ttrans = locale_expand (nestret, 0, nestlen - 1, start_lineno, );
-   free (nestret);
-
/* If we're supposed to single-quote translated strings,
   check whether the translated result is different from
   the original and single-quote the string if it is. */
if (singlequote_translations &&
  ((nestlen - 1) != ttranslen || STREQN (nestret, ttrans,
ttranslen) == 0))
  {
+   free (nestret);
if ((rflags & P_DQUOTE) == 0)
  nestret = sh_single_quote (ttrans);
else if ((rflags & P_DQUOTE) && (dolbrace_state ==
DOLBRACE_QUOTE2) && (flags & P_DOLBRACE))
@@ -3923,7 +3922,10 @@ parse_matched_pair (int qc, int open, int
close, size_t *lenp, int flags)
  nestret = sh_backslash_quote_for_double_quotes (ttrans, 0);
  }
else
- nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
+ {
+   free (nestret);
+   nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
+ }
free (ttrans);
nestlen = strlen (nestret);
retind -= 2; /* back up before the $" */



use-after-free in read_token_word

2023-03-15 Thread Grisha Levit
./bash --norc -O noexpand_translation -in <<<'$":"'

=ERROR: AddressSanitizer: heap-use-after-free on address 0x000108102b40
READ of size 1 thread T0
#0 read_token_word parse.y:5236
#1 read_token parse.y:3618

freed by thread T0 here:
#1 read_token_word parse.y:5231
#2 read_token parse.y:3618


diff --git a/parse.y b/parse.y
index e3516e2d..0a8c039a 100644
--- a/parse.y
+++ b/parse.y
@@ -5228,15 +5228,19 @@ read_token_word (int character)
/* PST_NOEXPAND */
/* Try to locale-expand the converted string. */
ttrans = locale_expand (ttok, 0, ttoklen - 1, first_line, );
-   free (ttok);
-
/* Add the double quotes back (or single quotes if the user
   has set that option). */
if (singlequote_translations &&
  ((ttoklen - 1) != ttranslen || STREQN (ttok, ttrans, ttranslen) == 0))
- ttok = sh_single_quote (ttrans);
+ {
+   free (ttok);
+   ttok = sh_single_quote (ttrans);
+ }
else
- ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
+ {
+   free (ttok);
+   ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
+ }

free (ttrans);
ttrans = ttok;



Re: Document that here strings don't support brace expansion.

2023-03-15 Thread Dale R. Worley
Chet Ramey  writes:
> If they're linked, why wouldn't saying filename generation isn't performed
> be enough to imply that brace expansion isn't performed either?

Hmm, yes, good point.

Dale



Re: Document that here strings don't support brace expansion.

2023-03-15 Thread Chet Ramey

On 3/15/23 12:52 AM, Alex Bochannek wrote:

Chet,

Thank you for the thoughtful responses. My thoughts below got a bit
long, so here is a summary:

- The here-string documentation should either spell out that brace
   expansion is not performed or simple only list the expansions that
   are.


The original text didn't describe the specific expansions for here-strings
at all, just deferred to the general description of redirections and here-
documents. I changed to the current text after an August 2011 discussion
where it was requested (in the midst of yet another riveting discussion of
the value of `set -e'). The fact that pathname expansion is not performed
was a particular sore point for at least one of the participants.

In general, I don't like enumerating expansions that aren't performed, but
it was the best way to resolve the issue here.


- The same goes for the documentation for the shell-expand-line Readline
   command.


Yes, I can make that explicit.


- A Readline command to expand braces is a nice to have, but not
   essential.


OK.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/




Re: Document that here strings don't support brace expansion.

2023-03-15 Thread alex xmb ratchev
On Wed, Mar 15, 2023, 8:07 AM Robert Elz  wrote:

> While it is probably useful to have every place where expansions occur list
> which ones apply, perhaps it would (also) be useful to include the general
> principle which controls all of this.
>
> That is, expansions are performed, late (just as commands are about to
> be run, after all parsing has finished, etc) in one of two basic contexts.
>
> In one, like in arg lists to commands (also the list after "in" in a for
> statement, and probablty more places I have forgotten), any number of words
> can be produced.  In those, all the expansions typically happen.
>
> In the other, exactly one word is required - like the word in var=${word}
> or the word in case ${word} in, or (in bash, and perhaps a couple of other
> shells) the word after a here string operator <<<${word} (and one more I
> will come to in a minute).   [The word after a here-doc redirect operator
> (<<)
> is strange for hysterical (oops: historical) reasons.]
>
> In those, the syntax allows for only one word to be produced, so performing
> field splitting, globbing, or brace expansion, all make no sense at all,
> and so the basic assumption, unless specified otherwise, is that none of
> those will happen.  (This is also why var="$@" is just plain stupid to
> write,
> and has unspecified consequences, though people keep doing it).
>
> quote removal always happens (everywhere).
>
> The one other place where just one word is required, and is all that
> makes sense, is after a redirect operator - the file name (or fd if the
> operator is >& or similar).   That is >${word} (etc).   For most shells
> none of the multi-word generating "expansions" happen there either, as
> there has to be exactly one filename to write into (in this example), not
> several.   However, at least when interactive, some shells perform globbing
> at this point, but require that only a single filename match the pattern
> (making it an error if more than one do) - just because users are too lazy
> to type the entire filename -- or use a func like:
>
> setfn()
> {
> var=$1; shift
> set -- "$@"
> case "$#" in
> 1) test -e "$1" && {
> eval "$var='$1'"
>
declare -g "$var=$1"

> return 0
>}
>printf >&2 'No match\n'
>return 1;
>;;
> esac
> printf >&2 'Ambiguous: %d files matched\n', "$#"
> return 1
> }
>
> Used like
> setfn f a*.txt
> after which, if it worked, you can use "$f" instead of the
> filename you are too lazy to type, which is shorter than a
> pattern guaranteed to only match one file will often be.
>
> Further it doesn't risk failing later, if something you do
> causes the pattern to later match more than one file (say you
> create abc-new.txt as a new version of abc.txt or save the
> old one as abc.was.txt).   "$f" doesn't change until you change it.
>
> Bash allows filename expansion after a redirect, at least in
> interactive shells (haven't tested it for non-interactive), it
> also performs brace expansion there - but that's largely guaranteed
> to fail, so I have no idea why - no field splitting though.
> Those exceptions to the general rule need to be clearly pointed out,
> but explaining every time something requires just one word, that
> some expansions don't happen, when in a context where it would be
> insane if they did, seems overdone.
>
> <<< requires a single word, as so all other redirect operators.
> Brace expansion, which has as its whole purpose, generating multiple
> words (as does field splitting, though it doesn't always succeed)
> (globbing merely can) should be obviously inappropriate there (just as
> it really should be after any redirect operator, which is why I
> was surprised to see
>
> $ cat < a{1,2,3}
> -bash: a{1,2,3}: ambiguous redirect
>
> rather than something more like
> -bash: a{1,2,3}: No such file or directory
>
> The only example of brace expansion actually "working" in a
> redirect, is something like
>
> $ cat  -bash: a1: No such file or directory
>
> but I am unable to think of any situation where doing that is
> better than just "cat  expanded, we know that either they have the same value, in which
> case we only need to use one of them  in which case we get an "ambiguous redirect error".   Crazy.
>
> kre
>
>
>


Re: Document that here strings don't support brace expansion.

2023-03-15 Thread Robert Elz
While it is probably useful to have every place where expansions occur list
which ones apply, perhaps it would (also) be useful to include the general
principle which controls all of this.

That is, expansions are performed, late (just as commands are about to
be run, after all parsing has finished, etc) in one of two basic contexts.

In one, like in arg lists to commands (also the list after "in" in a for
statement, and probablty more places I have forgotten), any number of words
can be produced.  In those, all the expansions typically happen.

In the other, exactly one word is required - like the word in var=${word}
or the word in case ${word} in, or (in bash, and perhaps a couple of other
shells) the word after a here string operator <<<${word} (and one more I
will come to in a minute).   [The word after a here-doc redirect operator (<<)
is strange for hysterical (oops: historical) reasons.]

In those, the syntax allows for only one word to be produced, so performing
field splitting, globbing, or brace expansion, all make no sense at all,
and so the basic assumption, unless specified otherwise, is that none of
those will happen.  (This is also why var="$@" is just plain stupid to write,
and has unspecified consequences, though people keep doing it).

quote removal always happens (everywhere).

The one other place where just one word is required, and is all that
makes sense, is after a redirect operator - the file name (or fd if the
operator is >& or similar).   That is >${word} (etc).   For most shells
none of the multi-word generating "expansions" happen there either, as
there has to be exactly one filename to write into (in this example), not
several.   However, at least when interactive, some shells perform globbing
at this point, but require that only a single filename match the pattern
(making it an error if more than one do) - just because users are too lazy
to type the entire filename -- or use a func like:

setfn()
{
var=$1; shift
set -- "$@"
case "$#" in
1) test -e "$1" && {
eval "$var='$1'"
return 0
   }
   printf >&2 'No match\n'
   return 1;
   ;;
esac
printf >&2 'Ambiguous: %d files matched\n', "$#"
return 1
}

Used like 
setfn f a*.txt
after which, if it worked, you can use "$f" instead of the
filename you are too lazy to type, which is shorter than a
pattern guaranteed to only match one file will often be.

Further it doesn't risk failing later, if something you do
causes the pattern to later match more than one file (say you
create abc-new.txt as a new version of abc.txt or save the
old one as abc.was.txt).   "$f" doesn't change until you change it.

Bash allows filename expansion after a redirect, at least in 
interactive shells (haven't tested it for non-interactive), it
also performs brace expansion there - but that's largely guaranteed
to fail, so I have no idea why - no field splitting though.
Those exceptions to the general rule need to be clearly pointed out,
but explaining every time something requires just one word, that
some expansions don't happen, when in a context where it would be
insane if they did, seems overdone.

<<< requires a single word, as so all other redirect operators.
Brace expansion, which has as its whole purpose, generating multiple
words (as does field splitting, though it doesn't always succeed)
(globbing merely can) should be obviously inappropriate there (just as
it really should be after any redirect operator, which is why I
was surprised to see

$ cat < a{1,2,3}
-bash: a{1,2,3}: ambiguous redirect

rather than something more like
-bash: a{1,2,3}: No such file or directory

The only example of brace expansion actually "working" in a
redirect, is something like

$ cat