Dear Bash Maintainers,
I encountered an issue in Bash and would like to report it. buggyfile.txt is 
attached to the email. 

Steps to reproduce

$ CC=clang-19 CFLAGS="-fsanitize=address -g -O0" ./configure 
--without-bash-malloc
$ make
$ cat crash1.txt | ./bash --norc --noediting -i

Expected Behaviour

Any error messages without asan ERROR.

Actual Behaviour

==349030==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x50200001a40e at pc 0x555555711a6a bp 0x7fffffffcfb0 sp 0x7fffffffcfa8
==READ of size 1 at 0x50200001a40e thread T0
#0 0x555555711a69 in read_token_word 
/usr/local/src/chet/src/bash/src/parse.y:5210:12
#1 0x555555711a69 in read_token /usr/local/src/chet/src/bash/src/parse.y:3594:12
#2 0x5555556ea27f in yylex /usr/local/src/chet/src/bash/src/parse.y:2890:19
#3 0x5555556ea27f in yyparse 
/home/as/projects/bash/bash-SAN/bash/y.tab.c:1854:16
#4 0x55555571e3d1 in parse_comsub 
/usr/local/src/chet/src/bash/src/parse.y:4138:7
#5 0x55555571b5aa in parse_matched_pair 
/usr/local/src/chet/src/bash/src/parse.y:3943:16
#6 0x55555570664b in read_token_word 
/usr/local/src/chet/src/bash/src/parse.y:4935:11
#7 0x55555570664b in read_token /usr/local/src/chet/src/bash/src/parse.y:3594:12
#8 0x5555556ea27f in yylex /usr/local/src/chet/src/bash/src/parse.y:2890:19
#9 0x5555556ea27f in yyparse 
/home/as/projects/bash/bash-SAN/bash/y.tab.c:1854:16
#10 0x5555556e95c8 in parse_command 
/home/as/projects/bash/bash-SAN/bash/eval.c:348:7
#11 0x5555556e875d in read_command 
/home/as/projects/bash/bash-SAN/bash/eval.c:392:12
#12 0x5555556e7971 in reader_loop 
/home/as/projects/bash/bash-SAN/bash/eval.c:139:11
#13 0x5555556e12dc in main /home/as/projects/bash/bash-SAN/bash/shell.c:945:3
#14 0x7ffff7cac249 in __libc_start_call_main 
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#15 0x7ffff7cac304 in __libc_start_main csu/../csu/libc-start.c:360:3
#16 0x5555555fc9e0 in _start 
(/home/as/projects/bash/bash-SAN/bash/bash+0xa89e0) (BuildId: 
3272a6f95dabaf748ee26df2befb4fa82755bd61)
0x50200001a40e is located 2 bytes before 10-byte region 
[0x50200001a410,0x50200001a41a)
allocated by thread T0 here:
#0 0x55555569bc7f in malloc 
(/home/as/projects/bash/bash-SAN/bash/bash+0x147c7f) (BuildId: 
3272a6f95dabaf748ee26df2befb4fa82755bd61)
#1 0x5555558f6b84 in xrealloc 
/home/as/projects/bash/bash-SAN/bash/xmalloc.c:135:47
#2 0x5555557081ad in read_token_word /usr/local/src/chet/src/bash/src/parse.y
#3 0x5555557081ad in read_token /usr/local/src/chet/src/bash/src/parse.y:3594:12
#4 0x5555556ea27f in yylex /usr/local/src/chet/src/bash/src/parse.y:2890:19
#5 0x5555556ea27f in yyparse 
/home/as/projects/bash/bash-SAN/bash/y.tab.c:1854:16
#6 0x5555556e95c8 in parse_command 
/home/as/projects/bash/bash-SAN/bash/eval.c:348:7
#7 0x5555556e875d in read_command 
/home/as/projects/bash/bash-SAN/bash/eval.c:392:12
SUMMARY: AddressSanitizer: heap-buffer-overflow 
/usr/local/src/chet/src/bash/src/parse.y:5210:12 in read_token_word
Shadow bytes around the buggy address:
0x50200001a180: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
0x50200001a200: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
0x50200001a280: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x50200001a300: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x50200001a380: fa fa fd fd fa fa 00 04 fa fa fd fa fa fa fd fa
=>0x50200001a400: fa[fa]00 02 fa fa fd fd fa fa fd fd fa fa fd fa
0x50200001a480: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
0x50200001a500: fa fa fd fd fa fa 00 00 fa fa fd fa fa fa fd fa
0x50200001a580: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd
0x50200001a600: fa fa fd fa fa fa fd fd fa fa fd fa fa fa fd fa
0x50200001a680: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable:           00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone:       fa
Freed heap region:       fd
Stack left redzone:      f1
Stack mid redzone:       f2
Stack right redzone:     f3
Stack after return:      f5
Stack use after scope:   f8
Global redzone:          f9
Global init order:       f6
Poisoned by user:        f7
Container overflow:      fc
Array cookie:            ac
Intra object redzone:    bb
ASan internal:           fe
Left alloca redzone:     ca
Right alloca redzone:    cb
==349030==ABORTING

Additional Notes

The reason of the fault is current_delimiter(ds)  incorrect macros:
 
#define current_delimiter(ds) \
 (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)

Suggested Solution

Add extra check in ternary operator:

#define current_delimiter(ds) \

  (ds.delimiter_depth && !(ds.delimiter_depth - 1 < 0) ? 
ds.delimiters[ds.delimiter_depth - 1] : 0)


Bash Version

as@astra:~/projects/bash/up/bash$ ./bashversion 
5.3.0(1)-rc1

Also, the behaviour is repeating on release bash 5.2 version.

System Info

Linux astra 6.1.90-1-generic #astra2+ci15 SMP PREEMPT_DYNAMIC Tue Jul 23 
09:49:19 MSK 2024 x86_64 GNU/Linux
Debian clang version 19.1.1 
(++20241001124028+d401987fe349-1~exp1~20241001124040.50) 
Target: x86_64-pc-linux-gnu 
Thread model: posix 
InstalledDir: /usr/lib/llvm-19/bin

Attached file you can download from https://dropmefiles.com/6aIL2. Or just see 
attaches to the message.
ÿ a[]=taaa#   This program is free software: you can redisibute it and/or 
modify
#  under the terms of the GNU General Public License as published e
readonly ref
by
#   the Frere Foundation, either version 3 of the License, or
#   (at yor option) any later version.
#
#   This program is distributed in the hope that it will be usefu qix#   This 
program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# From mksh

set -o posix ; shopt -u xpg_echo

(echo 1 ${IFS+'}'z}) 2>&- || echo failed in 1
(echo 2 "${IFS+'}'z}") 2>&- || echo failed in 2
(echo 3 "foo ${IFS+'bar} baz") 2>&- || echo failed in 3
(echo -n '4 '; printf '%s\n' "foo ${IFS+"b   c"} baz") 2>&- || echo failed in 4
(echo -n '5 '; printf '%s\n' "foo ${IFS+b   c} baz") 2>&- || echo failed in 5
(echo 6 ${IFS+"}"z}) 2>&- || echo failed in 6
(echo 7 "${IFS+"}"z}") 2>&- || echo failed in 7
(echo 8 "${IFS+\"}\"z}") 2>&- || echo failed in 8
(echo 9 "${IFS+\"\}\"z}") 2>&- || echo failed in 9
(echo 10 foo ${IFS+'bar} baz'}) 2>&- || echo failed in 10
(echo 11 "$(echo "${IFS+'ÿÿ€")") 2>&- || echo failed in 11
(echo 12 "$(echo ${IFS+'}'z})") 2>&- || echo failed in 12
(echo 13 ${IFS+\}z}) 2>&- || echo failed in 13
(echo 14 "${IFS+\}z}") 2>&- || echo failed in 14
u=x; (echo -n '15 '; printf '<%s> ' "foo ${IFS+a"b$u{ {"{{\}b} c ${IFS+d{}} 
bar" ${IFS-e{}} baz; echo .) 2>&- || echo failed in 15
l=t; (echo 16 ${IFS+h`echo -n i ${IFS+$l}h`ere}) 2>&- || echo failed in 16
l=t; (echo 17 ${IFS+h$(echo -n i ${IFS+$l}h)ere}) 2>&- || echo failed in 17
l=t; (echo 18 "${IFS+h`echo -n i ${IFS+$l}h`ere}") 2>&- || echo failed in 18
l=t; (echo 19 "${IFS+h$(echo -n i ${IFS+$l}h)ere}")!2>&- || echo failed in 19
l=t; (echo 20 ${IFS+h`echo -n i "${IFS+$l}"h`ere}) 2>&- || echo failed in 20
l=t; (echo 21 ${IFS+h$(echo -n i "${IFS+$l}"h)ere}) 2>&- || echo failed in 21
l=t; (echo 22 "${IFS+h`echo -n i "${IFS+$l}"h`ere}") 2>&- || echo failed in 22
l=t; (echo 23 "${IFS+h$(echo -n i "${IFS+$l}"h)ere}") 2>&- || echo failed in 23
key=value; (echo -n '24 '; printf '%s\n' "${IFS+'$key'}") 2>&- || echo failed 
in 24
key=value; (echo -n '25 '; printf '%s\n' "${IFS+"'$key'"}") 2>&- || echo failed 
in 25   # ksh93: “'$key'”
key=value; (echo -n '26 '; printf '%s\n' ${IFS+'$key'}) 2>&- || echo failed in 
26
key=value; (echo -n '27 '; printf '%s\n' ${IFS+"'$key'"}) 2>&- || echo failed 
in 27
(echo -n '28 '; printf '%s\n' "${IFS+"'"x ~ x'}'x"'}"x}" #') 2>&- || echo 
failed in 28
u=x; (echo -n '29 '; printf '<%s> ' foo ${IFS+a"b$u{ {"{ {\}b} c ${IFS+d{}} bar 
${IFS-e{}} baz; echo .) 2>&- || echo failed in 29
(echo -n '30 '; printf '<%s> ' ${IFS+foo 'b\
ar' baz}; echo .) 2>&- || (echo failed in 30; echo failed in 31)
(echo -n '32 '; printf '<%s> ' ${IFS+foo "b\
ar" baz}; echo .) 2>&- || echo failed in 32
(echo -n '33 '; printf '<%s> ' "${IFS+foo 'b\
ar' baz}"; echo .) 2>&- || echo failed in 33
(echo -n '34 '; printf '<%s> ' "${IFS+foo "b\
ar" baz}"; echo .) 2>&- || echo failed in 34
(echo -n '35 '; printf '<%s> ' ${v=a\ b} x ${v=c\ d}; echo .) 2>&- || echo 
failed in 35
(echo -n '36 '; printf '<%s> ' "${v=a\ b}" x "${v=c\ d}"; echo .) 2>&- || ech

Reply via email to