bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Infinite loop on parse_and_execute command substituion


From: Eduardo A . Bustamante López
Subject: Infinite loop on parse_and_execute command substituion
Date: Thu, 20 Sep 2018 01:23:50 -0700
User-agent: Mutt/1.10.1 (2018-07-13)

Found using AFL. The following causes bash 5.0 to get into an infinite loop:

(sorry for the junk reproducer, I don't know how to minimize non-crashing 
inputs)

bash-5.0$ IFS= read -r < <(base64 -d <<< 
'QCgusbGxw7GxsbGxsbGxsbGxKyQoKChzc3NzcwRpc3Nzc3Nzc3NzdnNzKSMpBymxsbGxsbGxsbGxsR4oGCgoVQ==');
 : ${REPLY@P}
(stuck)
^C

$ base64 -d <<< 
'QCgusbGxw7GxsbGxsbGxsbGxKyQoKChzc3NzcwRpc3Nzc3Nzc3NzdnNzKSMpBymxsbGxsbGxsbGxsR4oGCgoVQ=='
 | cat -A; echo
@(.M-1M-1M-1M-CM-1M-1M-1M-1M-1M-1M-1M-1M-1M-1M-1+$(((sssss^Disssssssssvss)#)^G)M-1M-1M-1M-1M-1M-1M-1M-1M-1M-1M-1^^(^X((U

0x000000000042f352 in discard_until (character=10) at ./parse.y:2665
2665      while ((c = shell_getc (0)) != EOF && c != character)
(gdb) bt
#0  0x000000000042f352 in discard_until (character=10) at ./parse.y:2665
#1  0x000000000042d176 in read_token (command=0) at ./parse.y:3253
#2  0x00000000004287fe in yylex () at ./parse.y:2744
#3  0x00000000004250de in yyparse () at y.tab.c:1823
#4  0x0000000000424b8f in parse_command () at eval.c:303
#5  0x00000000004bf238 in parse_and_execute (string=0x12a0a88 
"((sssss\004isssssssssvss)#)\a", from_file=0x53afa6 "command substitution", 
flags=20) at evalstring.c:352
#6  0x000000000047716b in command_substitute (string=0x12a0a88 
"((sssss\004isssssssssvss)#)\a", quoted=1, flags=0) at subst.c:6278
#7  0x000000000047bc51 in param_expand (string=0x13add88 
"@(.\261\261\261ñ\261\261\261\261\261\261\261\261\261\261+$(((sssss\004isssssssssvss)#)\a)",
 '\261' <repeats 11 times>, "\036(\030((U", 
    sindex=0x7ffea8aa1e6c, quoted=1, expanded_something=0x0, 
contains_dollar_at=0x7ffea8aa1e54, quoted_dollar_at_p=0x7ffea8aa1e68, 
had_quoted_null_p=0x7ffea8aa1e60, pflags=0) at subst.c:9415
#8  0x000000000047345a in expand_word_internal (word=0x7ffea8aa1f20, quoted=1, 
isexp=0, contains_dollar_at=0x0, expanded_something=0x0) at subst.c:9887
#9  0x00000000004726ce in expand_prompt_string (string=0x13add08 
"@(.\261\261\261ñ\261\261\261\261\261\261\261\261\261\261+$(((sssss\004isssssssssvss)#)\a)",
 '\261' <repeats 11 times>, "\036(\030((U", 
    quoted=1, wflags=0) at subst.c:3804
#10 0x000000000042c80c in decode_prompt_string (string=0x13ad4c9 "A") at 
./parse.y:6065
#11 0x00000000004851fc in string_transform (xc=80, v=0x12a0e48, 
    s=0x13ad488 
"@(.\261\261\261ñ\261\261\261\261\261\261\261\261\261\261+$(((sssss\004isssssssssvss)#)\a)",
 '\261' <repeats 11 times>, "\036(\030((U") at subst.c:7468
#12 0x000000000048224d in parameter_brace_transform (varname=0x12a05a8 "REPLY", 
    value=0x13adc08 
"@(.\261\261\261ñ\261\261\261\261\261\261\261\261\261\261+$(((sssss\004isssssssssvss)#)\a)",
 '\261' <repeats 11 times>, "\036(\030((U", ind=0, xform=0x1315e18 "P", 
rtype=64, quoted=0, 
    pflags=0, flags=0) at subst.c:7616
#13 0x000000000047ebeb in parameter_brace_expand (string=0x129f808 
"${REPLY@P}", indexp=0x7ffea8aa34d4, quoted=0, pflags=0, 
quoted_dollar_atp=0x7ffea8aa3718, contains_dollar_at=0x7ffea8aa3704) at 
subst.c:8884
#14 0x000000000047b89a in param_expand (string=0x129f808 "${REPLY@P}", 
sindex=0x7ffea8aa371c, quoted=0, expanded_something=0x7ffea8aa389c, 
contains_dollar_at=0x7ffea8aa3704, quoted_dollar_at_p=0x7ffea8aa3718, 
    had_quoted_null_p=0x7ffea8aa3710, pflags=0) at subst.c:9316
#15 0x000000000047345a in expand_word_internal (word=0x12a1848, quoted=0, 
isexp=0, contains_dollar_at=0x7ffea8aa3898, expanded_something=0x7ffea8aa389c) 
at subst.c:9887
#16 0x0000000000487315 in shell_expand_word_list (tlist=0x12a17a8, eflags=31) 
at subst.c:11233
#17 0x0000000000478b63 in expand_word_list_internal (list=0x12a02a8, eflags=31) 
at subst.c:11357
#18 0x00000000004789aa in expand_words (list=0x12a02a8) at subst.c:10877
#19 0x00000000004430e0 in execute_simple_command (simple_command=0x12a0448, 
pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x129f828) at execute_cmd.c:4278
#20 0x00000000004412ab in execute_command_internal (command=0x12a0a08, 
asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x129f828) at 
execute_cmd.c:840
#21 0x0000000000445208 in execute_connection (command=0x12a1248, 
asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x129f828) at 
execute_cmd.c:2689
#22 0x0000000000441681 in execute_command_internal (command=0x12a1248, 
asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x129f828) at 
execute_cmd.c:1013
#23 0x000000000044087b in execute_command (command=0x12a1248) at 
execute_cmd.c:394
#24 0x00000000004247da in reader_loop () at eval.c:175
#25 0x0000000000421aad in main (argc=1, argv=0x7ffea8aa3ed8, 
env=0x7ffea8aa3ee8) at shell.c:805
(gdb) n
2665      while ((c = shell_getc (0)) != EOF && c != character)
(gdb) 
2665      while ((c = shell_getc (0)) != EOF && c != character)
(gdb) p c
$1 = 32
(gdb) n
2665      while ((c = shell_getc (0)) != EOF && c != character)
(gdb) p c
$2 = 32

It seems to have been introduced by commit 
911ae06ca9e2b6e9778bfb2e0d8c04bfcc568beb, described as:

+                                  1/11
+                                  ----
+parse.y
+       - shell_getc: move code that decides whether to append a space to an
+         alias expansion here from mk_alexpansion, so we can inhibit adding
+         a space if we're currently parsing a single or double quoted string

I checked out the previous commit, 879213c6308fab5a1f8a29fc607e7069b940537c, 
and it works fine:

bash-4.4$ IFS= read -r < <(base64 -d <<< 
'QCgusbGxw7GxsbGxsbGxsbGxKyQoKChzc3NzcwRpc3Nzc3Nzc3NzdnNzKSMpBymxsbGxsbGxsbGxsR4oGCgoVQ==');
 : ${REPLY@P}
bash: command substitution: line 2: syntax error: unexpected end of file

For some reason, it's looping here:

#ifndef OLD_ALIAS_HACK
  if (uc == 0 && pushed_string_list && pushed_string_list->flags != PSH_SOURCE 
&&
      shell_input_line_index > 0 &&
      shell_input_line[shell_input_line_index-1] != ' ' &&
      shell_input_line[shell_input_line_index-1] != '\n' &&
      shellmeta (shell_input_line[shell_input_line_index-1]) == 0 &&
      (current_delimiter (dstack) != '\'' && current_delimiter (dstack) != '"'))
    {
      return ' ';   /* END_ALIAS */
    }
#endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]