Read builtin -e (readline) oddities

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Read builtin -e (readline) oddities

Eduardo A. Bustamante López
I'm trying to figure out a way to fuzz >>read -e -d ""<<, without having the
fuzzer break due to the temporary files created by fc.

While doing this, I noticed the oddities described below.


#1
Hit `C-x C-e' twice.  The value of PATH seems to be ignored for the second
line.

  dualbus@debian:~$ PATH= read -e
 
  bash: vim: No such file or directory
 
  echo hi
  hi


#2
Spurious `;'s are inserted into the history.

  dualbus@debian:~$ history -c
  dualbus@debian:~$ PATH= read -e
 
  bash: vim: No such file or directory
 
  echo hi
  hi
 
  dualbus@debian:~$ history
      1  PATH= read -e; ;
      2  echo hi
      3  history


#3
Hit `C-x C-e' thrice. Also, the mapping of `\C-m' became `self-insert' instead
of `accept-line'.

  dualbus@debian:~$ PATH= EDITOR=: read -e -d ''
 
  PATH= EDITOR=: read -e -d '';
 
  fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
  : /tmp/bash-fc.IZAzmF
  PATH= EDITOR=: read -e -d ''; ;
  bash: syntax error near unexpected token `;'
 
  fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
  vim /tmp/bash-fc.35ePED
  ^M^M^C
  dualbus@debian:~$ ^M^M^M^M^M^M^M^M



In relation to my fuzzing goal, it seems this is what I wanted:

  dualbus@debian:~$ (enable -n fc; read -e -d '')
 
  bash: fc: command not found
 
  bash: fc: command not found
 
  bash: fc: command not found
 
  bash: fc: command not found
 
  bash: fc: command not found
  ^C

--
Eduardo Bustamante
https://dualbus.me/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Chet Ramey
On 6/18/17 9:39 PM, Eduardo A. Bustamante López wrote:
> I'm trying to figure out a way to fuzz >>read -e -d ""<<, without having the
> fuzzer break due to the temporary files created by fc.
>
> While doing this, I noticed the oddities described below.
>
>
> #1
> Hit `C-x C-e' twice.  The value of PATH seems to be ignored for the second
> line.

I can't reproduce this.  I suspect one of your startup files is somehow
being read and setting PATH. It may also be an interaction with the
command-not-found hook.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Eduardo A. Bustamante López
On Mon, Jun 19, 2017 at 10:08:30AM -0400, Chet Ramey wrote:
[...]
> I can't reproduce this.  I suspect one of your startup files is somehow
> being read and setting PATH. It may also be an interaction with the
> command-not-found hook.

Hm, I can still reproduce it under Debian 9, using the `devel' branch, and I'm
sure no startup files are being sourced.

  dualbus@debian:~/src/gnu/bash-builds/devel$ ./bash --norc --noprofile
  bash-4.4$ declare -p command-not-found
  bash: declare: command-not-found: not found
  bash-4.4$
  GNU bash, version 4.4.12(3)-maint (x86_64-unknown-linux-gnu)
  bash-4.4$ PATH= read -e
 
  bash: vim: No such file or directory
 
  echo this is vim
  this is vim

I then patched bash like this:

  dualbus@debian:~/src/gnu/bash$ git diff -- execute_cmd.c
  diff --git a/execute_cmd.c b/execute_cmd.c
  index 0183a105..50f4e2f0 100644
  --- a/execute_cmd.c
  +++ b/execute_cmd.c
  @@ -5550,6 +5550,7 @@ shell_execve (command, args, env)
     char sample[HASH_BANG_BUFSIZ];
     int sample_len;
   
  +  if (strlen(get_string_value ("PATH")) > 0) abort();
     SETOSTYPE (0);               /* Some systems use for USG/POSIX semantics */
     execve (command, args, env);
     i = errno;                   /* error from execve() */

And I got (the first `\C-x \C-e' gets to shell_execve, but PATH is empty):

  dualbus@debian:~/src/gnu/bash-builds/devel$ ./bash --norc --noprofile
  bash-4.4$ ulimit -c unlimited
  bash-4.4$
  GNU bash, version 4.4.12(9)-maint (x86_64-unknown-linux-gnu)
  bash-4.4$ PATH= read -e
 
  bash: vim: No such file or directory
 
  Aborted (core dumped)
 
  Core was generated by `./bash --norc --noprofile'.
  Program terminated with signal SIGABRT, Aborted.
  #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
  51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
  (gdb) bt
  #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
  #1  0x00007f30b14c93fa in __GI_abort () at abort.c:89
  #2  0x000055a0df6527c4 in shell_execve (command=0x55a0e0a21020 "/usr/bin/vim", args=0x55a0e0a64610, env=0x55a0e0a207f0) at ../../bash/execute_cmd.c:5553
  #3  0x000055a0df6525b1 in execute_disk_command (words=0x55a0e0a63c20, redirects=0x0, command_line=0x55a0e0a20f60 "vim /tmp/bash-fc.HTeaRz", pipe_in=-1, pipe_out=-1, async=0,
      fds_to_close=0x55a0e0a42d80, cmdflags=0) at ../../bash/execute_cmd.c:5348
  #4  0x000055a0df650d4f in execute_simple_command (simple_command=0x55a0e0a62780, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x55a0e0a42d80) at ../../bash/execute_cmd.c:4466
  #5  0x000055a0df64a465 in execute_command_internal (command=0x55a0e0a20e80, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x55a0e0a42d80) at ../../bash/execute_cmd.c:811
  #6  0x000055a0df6ad6a8 in parse_and_execute (string=0x55a0e0a61b10 "vim /tmp/bash-fc.HTeaRz", from_file=0x55a0df71cecd "fc", flags=4) at ../../../bash/builtins/evalstring.c:430
  #7  0x000055a0df6aee93 in fc_builtin (list=0x0) at ../../../bash/builtins/../../../bash/builtins/fc.def:438
  #8  0x000055a0df6511cb in execute_builtin (builtin=0x55a0df6ae4ae <fc_builtin>, words=0x55a0e0a625d0, flags=0, subshell=0) at ../../bash/execute_cmd.c:4609
  #9  0x000055a0df6520a7 in execute_builtin_or_function (words=0x55a0e0a625d0, builtin=0x55a0df6ae4ae <fc_builtin>, var=0x0, redirects=0x0, fds_to_close=0x55a0e0a63df0, flags=0)
      at ../../bash/execute_cmd.c:5107
  #10 0x000055a0df650ad1 in execute_simple_command (simple_command=0x55a0e0a62540, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x55a0e0a63df0) at ../../bash/execute_cmd.c:4395
  #11 0x000055a0df64a465 in execute_command_internal (command=0x55a0e0a20400, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x55a0e0a63df0) at ../../bash/execute_cmd.c:811
  #12 0x000055a0df6ad6a8 in parse_and_execute (string=0x55a0e0a613b0 "fc -e \"${VISUAL:-${EDITOR:-emacs}}\"", from_file=0x55a0df70ccd5 "C-xC-e", flags=4)
      at ../../../bash/builtins/evalstring.c:430
  #13 0x000055a0df696203 in edit_and_execute_command (count=1, c=5, editing_mode=1, edit_command=0x55a0df70cd10 "fc -e \"${VISUAL:-${EDITOR:-emacs}}\"") at ../../bash/bashline.c:977
  #14 0x000055a0df6962f0 in emacs_edit_and_execute_command (count=1, c=5) at ../../bash/bashline.c:1013
  #15 0x000055a0df6dccd5 in _rl_dispatch_subseq (key=5, map=0x55a0df9461a0 <emacs_ctlx_keymap>, got_subseq=0) at ../../../../bash/lib/readline/readline.c:851
  #16 0x000055a0df6dd19a in _rl_dispatch_subseq (key=24, map=0x55a0df944160 <emacs_standard_keymap>, got_subseq=0) at ../../../../bash/lib/readline/readline.c:985
  #17 0x000055a0df6dca4c in _rl_dispatch (key=-1320386609, map=0x55a0df944160 <emacs_standard_keymap>) at ../../../../bash/lib/readline/readline.c:797
  #18 0x000055a0df6dc6d4 in readline_internal_char () at ../../../../bash/lib/readline/readline.c:629
  #19 0x000055a0df6dc72c in readline_internal_charloop () at ../../../../bash/lib/readline/readline.c:656
  #20 0x000055a0df6dc750 in readline_internal () at ../../../../bash/lib/readline/readline.c:670
  #21 0x000055a0df6dc16d in readline (prompt=0x55a0df71d63c "") at ../../../../bash/lib/readline/readline.c:374
  #22 0x000055a0df6b6407 in edit_line (p=0x55a0df71d63c "", itext=0x0) at ../../../bash/builtins/../../../bash/builtins/read.def:1095
  #23 0x000055a0df6b5243 in read_builtin (list=0x0) at ../../../bash/builtins/../../../bash/builtins/read.def:559
  #24 0x000055a0df6511cb in execute_builtin (builtin=0x55a0df6b44f9 <read_builtin>, words=0x55a0e0a60ed0, flags=0, subshell=0) at ../../bash/execute_cmd.c:4609
  #25 0x000055a0df6520a7 in execute_builtin_or_function (words=0x55a0e0a60ed0, builtin=0x55a0df6b44f9 <read_builtin>, var=0x0, redirects=0x0, fds_to_close=0x55a0e0a61070, flags=0)
      at ../../bash/execute_cmd.c:5107
  #26 0x000055a0df650ad1 in execute_simple_command (simple_command=0x55a0e0a60df0, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x55a0e0a61070) at ../../bash/execute_cmd.c:4395
  #27 0x000055a0df64a465 in execute_command_internal (command=0x55a0e0a42ba0, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x55a0e0a61070) at ../../bash/execute_cmd.c:811
  #28 0x000055a0df6499c1 in execute_command (command=0x55a0e0a42ba0) at ../../bash/execute_cmd.c:393
  #29 0x000055a0df633a2a in reader_loop () at ../../bash/eval.c:172
  #30 0x000055a0df631677 in main (argc=3, argv=0x7fff33cecb28, env=0x7fff33cecb48) at ../../bash/shell.c:794

  (gdb) frame
  #2  0x000055a0df6527c4 in shell_execve (command=0x55a0e0a21020 "/usr/bin/vim", args=0x55a0e0a64610, env=0x55a0e0a207f0) at ../../bash/execute_cmd.c:5553
  5553      if (strlen(get_string_value ("PATH")) > 0) abort();
  (gdb) p env[30]
  $15 = 0x55a0e0a21140 "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
  (gdb) p env[5]
  $16 = 0x55a0e0a61460 "EDITOR=vim"


This works fine though:

  dualbus@debian:~/src/gnu/bash-builds/devel$ ./bash --norc --noprofile
  bash-4.4$ export PATH=
  bash-4.4$ read -e
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
  ^C

So it seems that the problem is that the tempenv is reset for the second
execution of the `fc' builtin.



And in the case of getting the extra `;'s in the history, it would seem it adds
one per failed execve:

  bash-4.4$ history -c
  bash-4.4$ export PATH=
  bash-4.4$ read -e
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
 
  bash: vim: No such file or directory
  bash-4.4$ history
      1  export PATH=
      2  read -e; ; ; ; ;
      3  history

--
Eduardo Bustamante
https://dualbus.me/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Eduardo A. Bustamante López
On Mon, Jun 19, 2017 at 9:57 AM, Eduardo A. Bustamante López
<[hidden email]> wrote:
[...]
> Hm, I can still reproduce it under Debian 9, using the `devel' branch, and I'm
> sure no startup files are being sourced.
>
>   dualbus@debian:~/src/gnu/bash-builds/devel$ ./bash --norc --noprofile
>   bash-4.4$ declare -p command-not-found
>   bash: declare: command-not-found: not found

Heh, actually:

dualbus@debian:~/src/gnu/bash-builds/devel$ ./bash --norc --noprofile
bash-4.4$ declare -fp command_not_found_handle
bash: declare: command_not_found_handle: not found

The rest is correct though.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Chet Ramey
In reply to this post by Eduardo A. Bustamante López
On 6/18/17 9:39 PM, Eduardo A. Bustamante López wrote:

> #1
> Hit `C-x C-e' twice.  The value of PATH seems to be ignored for the second
> line.

The shell should ensure that the temporary env is preserved across the
entire execution of any builtin that can call parse_and_execute (like `fc'
and `read' when using `read -e').

> #2
> Spurious `;'s are inserted into the history.

The fc builtin (via edit_and_execute_command) shouldn't try to insert empty
lines into the history list.  The only time this can happen is via
`read -e'.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Chet Ramey
In reply to this post by Eduardo A. Bustamante López
On 6/18/17 9:39 PM, Eduardo A. Bustamante López wrote:

> I'm trying to figure out a way to fuzz >>read -e -d ""<<, without having the
> fuzzer break due to the temporary files created by fc.
>
> While doing this, I noticed the oddities described below.
>
>
> #1
> Hit `C-x C-e' twice.  The value of PATH seems to be ignored for the second
> line.
>
>   dualbus@debian:~$ PATH= read -e
>  
>   bash: vim: No such file or directory
>  
>   echo hi
>   hi
>
>
> #2
> Spurious `;'s are inserted into the history.
>
>   dualbus@debian:~$ history -c
>   dualbus@debian:~$ PATH= read -e
>  
>   bash: vim: No such file or directory
>  
>   echo hi
>   hi
>  
>   dualbus@debian:~$ history
>       1  PATH= read -e; ;
>       2  echo hi
>       3  history
>
>
> #3
> Hit `C-x C-e' thrice. Also, the mapping of `\C-m' became `self-insert' instead
> of `accept-line'.

`read -e' changes it because it's no longer the line delimiter.

>   dualbus@debian:~$ PATH= EDITOR=: read -e -d ''
>  
>   PATH= EDITOR=: read -e -d '';
>  
>   fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
>   : /tmp/bash-fc.IZAzmF
>   PATH= EDITOR=: read -e -d ''; ;
>   bash: syntax error near unexpected token `;'
>  
>   fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
>   vim /tmp/bash-fc.35ePED
>   ^M^M^C

I'll have to check why it doesn't get restored on ^C.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Read builtin -e (readline) oddities

Chet Ramey
On 6/19/17 3:40 PM, Chet Ramey wrote:

>> #3
>> Hit `C-x C-e' thrice. Also, the mapping of `\C-m' became `self-insert' instead
>> of `accept-line'.
>
> `read -e' changes it because it's no longer the line delimiter.
>
>>   dualbus@debian:~$ PATH= EDITOR=: read -e -d ''
>>  
>>   PATH= EDITOR=: read -e -d '';
>>  
>>   fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
>>   : /tmp/bash-fc.IZAzmF
>>   PATH= EDITOR=: read -e -d ''; ;
>>   bash: syntax error near unexpected token `;'
>>  
>>   fc -e "${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}"
>>   vim /tmp/bash-fc.35ePED
>>   ^M^M^C
>
> I'll have to check why it doesn't get restored on ^C.

It does get restored, but the code only has one level of restoration, so
the recursive calls overwrite it.  Who's going to do multiple levels of
edit-and-execute-command?

If you want to run multiple recursive versions of edit-and-execute-
command, you should be savvy enough to get out using ^@ (control-shift-2),
right? :-)

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Loading...