Out-of-bound read in function msg_outtrans_attr in vim/vim
Reported on
Jun 23rd 2022
Description
Out-of-bound read in function msg_outtrans_attr
at message.c:1551
Version
commit 8eba2bd291b347e3008aa9e565652d51ad638cfa (HEAD -> master, tag: v8.2.5151)
Proof of Concept
./vim/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S poc_vim01 -c :qa!
=================================================================
==21232==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x619000000981 at pc 0x7faf43c4f66e bp 0x7ffd3a3d8b10 sp 0x7ffd3a3d82b8
READ of size 620 at 0x619000000981 thread T0
#0 0x7faf43c4f66d (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5166d)
#1 0x562f077dacc5 in msg_outtrans_attr /home/guest/trung/vim/src/message.c:1551
#2 0x562f077d4777 in msg_attr_keep /home/guest/trung/vim/src/message.c:176
#3 0x562f077d4550 in msg_attr /home/guest/trung/vim/src/message.c:123
#4 0x562f077d7aec in msg_trunc_attr /home/guest/trung/vim/src/message.c:933
#5 0x562f072d8239 in process_next_cpt_value /home/guest/trung/vim/src/insexpand.c:3271
#6 0x562f072daed2 in ins_compl_get_exp /home/guest/trung/vim/src/insexpand.c:3743
#7 0x562f072dbba5 in find_next_completion_match /home/guest/trung/vim/src/insexpand.c:3992
#8 0x562f072dbf6e in ins_compl_next /home/guest/trung/vim/src/insexpand.c:4093
#9 0x562f072df01d in ins_complete /home/guest/trung/vim/src/insexpand.c:4944
#10 0x562f0713b591 in edit /home/guest/trung/vim/src/edit.c:1281
#11 0x562f073ac613 in invoke_edit /home/guest/trung/vim/src/normal.c:7035
#12 0x562f073a7135 in n_opencmd /home/guest/trung/vim/src/normal.c:6279
#13 0x562f073aeb89 in nv_open /home/guest/trung/vim/src/normal.c:7416
#14 0x562f073843de in normal_cmd /home/guest/trung/vim/src/normal.c:939
#15 0x562f0720b759 in exec_normal /home/guest/trung/vim/src/ex_docmd.c:8812
#16 0x562f0720b535 in exec_normal_cmd /home/guest/trung/vim/src/ex_docmd.c:8775
#17 0x562f0720add6 in ex_normal /home/guest/trung/vim/src/ex_docmd.c:8693
#18 0x562f071e76d6 in do_one_cmd /home/guest/trung/vim/src/ex_docmd.c:2570
#19 0x562f071dea5c in do_cmdline /home/guest/trung/vim/src/ex_docmd.c:992
#20 0x562f074ff9cb in do_source_ext /home/guest/trung/vim/src/scriptfile.c:1674
#21 0x562f07500b0d in do_source /home/guest/trung/vim/src/scriptfile.c:1801
#22 0x562f074fd646 in cmd_source /home/guest/trung/vim/src/scriptfile.c:1174
#23 0x562f074fd6a7 in ex_source /home/guest/trung/vim/src/scriptfile.c:1200
#24 0x562f071e76d6 in do_one_cmd /home/guest/trung/vim/src/ex_docmd.c:2570
#25 0x562f071dea5c in do_cmdline /home/guest/trung/vim/src/ex_docmd.c:992
#26 0x562f071dce5b in do_cmdline_cmd /home/guest/trung/vim/src/ex_docmd.c:586
#27 0x562f077cda63 in exe_commands /home/guest/trung/vim/src/main.c:3133
#28 0x562f077c6c58 in vim_main2 /home/guest/trung/vim/src/main.c:780
#29 0x562f077c6514 in main /home/guest/trung/vim/src/main.c:432
#30 0x7faf42e5ac86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
#31 0x562f07068a99 in _start (/home/guest/trung/vim/src/vim+0x137a99)
0x619000000981 is located 0 bytes to the right of 1025-byte region [0x619000000580,0x619000000981)
allocated by thread T0 here:
#0 0x7faf43cdcb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
#1 0x562f07068edf in lalloc /home/guest/trung/vim/src/alloc.c:246
#2 0x562f07068ce4 in alloc /home/guest/trung/vim/src/alloc.c:151
#3 0x562f077c6e7c in common_init /home/guest/trung/vim/src/main.c:914
#4 0x562f077c6222 in main /home/guest/trung/vim/src/main.c:185
#5 0x7faf42e5ac86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5166d)
Shadow bytes around the buggy address:
0x0c327fff80e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff80f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c327fff8130:[01]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c327fff8140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c327fff8150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c327fff8180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==21232==ABORTING
Attachment
Impact
This may result in corruption of sensitive information, a crash, or code execution among other things.
I cannot reproduce the problem, valgrind output is empty.
My compile commands are below:
git checkout 8eba2bd291b347e3008aa9e565652d51ad638cfa
CFLAGS="-fsanitize=address -g" CXXFLAGS="-fsanitize=address -g" LDFLAGS="-fsanitize=address" ./configure --prefix=/home/guest/trung/install_vim2
make -j2
Then I run
./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S poc_vim01 -c :qa!
I can still reproduce the problem with the latest version, which is 8.2.5155
at the moment.
I tried to compile vim without ASAN:
./configure --prefix=/home/guest/trung/install_vim2
make -j2
My valgrind
is showing the result
$ valgrind ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S poc_vim01 -c :qa!
==19219== Memcheck, a memory error detector
==19219== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19219== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==19219== Command: ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S poc_vim01 -c :qa!
==19219==
==19219== Conditional jump or move depends on uninitialised value(s)
==19219== at 0x4C34D08: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19219== by 0x38774F: msg_outtrans_attr (message.c:1551)
==19219== by 0x387B03: msg_attr_keep (message.c:176)
==19219== by 0x387F73: msg_attr (message.c:123)
==19219== by 0x387F73: msg_trunc_attr (message.c:933)
==19219== by 0x1FE1B4: process_next_cpt_value (insexpand.c:3271)
==19219== by 0x1FE1B4: ins_compl_get_exp (insexpand.c:3743)
==19219== by 0x1FE1B4: find_next_completion_match (insexpand.c:3992)
==19219== by 0x1FE1B4: ins_compl_next (insexpand.c:4093)
==19219== by 0x1FE72A: ins_complete (insexpand.c:4944)
==19219== by 0x180426: edit (edit.c:1281)
==19219== by 0x22F599: invoke_edit.isra.1 (normal.c:7035)
==19219== by 0x2317D1: n_opencmd (normal.c:6279)
==19219== by 0x2317D1: nv_open (normal.c:7416)
==19219== by 0x2385B4: normal_cmd (normal.c:939)
==19219== by 0x1B671C: exec_normal (ex_docmd.c:8807)
==19219== by 0x1B697F: ex_normal (ex_docmd.c:8693)
==19219==
==19219==
==19219== HEAP SUMMARY:
==19219== in use at exit: 73,436 bytes in 382 blocks
==19219== total heap usage: 1,227 allocs, 845 frees, 416,677 bytes allocated
==19219==
==19219== LEAK SUMMARY:
==19219== definitely lost: 0 bytes in 0 blocks
==19219== indirectly lost: 0 bytes in 0 blocks
==19219== possibly lost: 139 bytes in 8 blocks
==19219== still reachable: 73,297 bytes in 374 blocks
==19219== suppressed: 0 bytes in 0 blocks
==19219== Rerun with --leak-check=full to see details of leaked memory
==19219==
==19219== For counts of detected and suppressed errors, rerun with: -v
==19219== Use --track-origins=yes to see where uninitialised values come from
==19219== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
valgrind
version:
$ valgrind --version
valgrind-3.13.0
vim
version
$ ./vim2/src/vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jun 25 2022 00:35:46)
Included patches: 1-5151
Compiled by guest@elk
Huge version without GUI. Features included (+) or not (-):
+acl +file_in_path +mouse_urxvt -tag_any_white
+arabic +find_in_path +mouse_xterm -tcl
+autocmd +float +multi_byte +termguicolors
+autochdir +folding +multi_lang +terminal
-autoservername -footer -mzscheme +terminfo
-balloon_eval +fork() +netbeans_intg +termresponse
+balloon_eval_term -gettext +num64 +textobjects
-browse -hangul_input +packages +textprop
++builtin_terms +iconv +path_extra +timers
+byte_offset +insert_expand -perl +title
+channel +ipv6 +persistent_undo -toolbar
+cindent +job +popupwin +user_commands
-clientserver +jumplist +postscript +vartabs
-clipboard +keymap +printer +vertsplit
+cmdline_compl +lambda +profile +vim9script
+cmdline_hist +langmap -python +viminfo
+cmdline_info +libcall -python3 +virtualedit
+comments +linebreak +quickfix +visual
+conceal +lispindent +reltime +visualextra
+cryptv +listcmds +rightleft +vreplace
+cscope +localmap -ruby +wildignore
+cursorbind -lua +scrollbind +wildmenu
+cursorshape +menu +signs +windows
+dialog_con +mksession +smartindent +writebackup
+diff +modify_fname -sodium -X11
+digraphs +mouse -sound -xfontset
-dnd -mouseshape +spell -xim
-ebcdic +mouse_dec +startuptime -xpm
+emacs_tags -mouse_gpm +statusline -xsmp
+eval -mouse_jsbterm -sun_workshop -xterm_clipboard
+ex_extra +mouse_netterm +syntax -xterm_save
+extra_search +mouse_sgr +tag_binary
-farsi -mouse_sysmouse -tag_old_static
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/home/guest/trung/install_vim2/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -g -O2 -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lm -ltinfo -lrt -ldl
In the POC the CTRL-N command is used in Insert mode. Perhaps for how you start Vim (in which directory) makes a difference. What if you make the "src" directory the current directory? You can also see if changing the 'complete' option makes a difference.
Note that at insexpand.c:3271 the messag is "Scanning tags.", which is very short. Do you perhaps the environment set to translated messages? What is $LANG or $LC_ALL set to?
I try to run vim
with the current directory is set to vim2/src
:
guest@elk:~/trung/vim2/src$ valgrind ./vim -u NONE -i NONE -n -m -X -Z -e -s -S ../../poc_vim01 -c :qa!
==956== Memcheck, a memory error detector
==956== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==956== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==956== Command: ./vim -u NONE -i NONE -n -m -X -Z -e -s -S ../../poc_vim01 -c :qa!
==956==
==956== Conditional jump or move depends on uninitialised value(s)
==956== at 0x4C34D08: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==956== by 0x38774F: msg_outtrans_attr (message.c:1551)
==956== by 0x387B03: msg_attr_keep (message.c:176)
==956== by 0x387F73: msg_attr (message.c:123)
==956== by 0x387F73: msg_trunc_attr (message.c:933)
==956== by 0x1FE1B4: process_next_cpt_value (insexpand.c:3271)
==956== by 0x1FE1B4: ins_compl_get_exp (insexpand.c:3743)
==956== by 0x1FE1B4: find_next_completion_match (insexpand.c:3992)
==956== by 0x1FE1B4: ins_compl_next (insexpand.c:4093)
==956== by 0x1FE72A: ins_complete (insexpand.c:4944)
==956== by 0x180426: edit (edit.c:1281)
==956== by 0x22F599: invoke_edit.isra.1 (normal.c:7035)
==956== by 0x2317D1: n_opencmd (normal.c:6279)
==956== by 0x2317D1: nv_open (normal.c:7416)
==956== by 0x2385B4: normal_cmd (normal.c:939)
==956== by 0x1B671C: exec_normal (ex_docmd.c:8807)
==956== by 0x1B697F: ex_normal (ex_docmd.c:8693)
==956==
==956==
==956== HEAP SUMMARY:
==956== in use at exit: 73,433 bytes in 382 blocks
==956== total heap usage: 1,227 allocs, 845 frees, 416,842 bytes allocated
==956==
==956== LEAK SUMMARY:
==956== definitely lost: 0 bytes in 0 blocks
==956== indirectly lost: 0 bytes in 0 blocks
==956== possibly lost: 139 bytes in 8 blocks
==956== still reachable: 73,294 bytes in 374 blocks
==956== suppressed: 0 bytes in 0 blocks
==956== Rerun with --leak-check=full to see details of leaked memory
==956==
==956== For counts of detected and suppressed errors, rerun with: -v
==956== Use --track-origins=yes to see where uninitialised values come from
==956== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the output of my locale
:
guest@elk:~/trung/vim2/src$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
The stack trace looks much like from here I also try changing the whole environment using these commands:
export LC_ALL=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
But still get the error
Perhaps the width of the terminal matters? A smaller width may cause the truncation to kick in. I tried a few sizes but still cannot reproduce the problem.
Yes, I think the height and the width of the terminal matters. You can use this command to print out the size of the terminal
stty size
With width = 209, height = 52, it crashes
guest@elk:~/trung$ stty size
52 209
guest@elk:~/trung$ valgrind ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S ./poc_vim01 -c ':qa!'
==27959== Memcheck, a memory error detector
==27959== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27959== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27959== Command: ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S ./poc_vim01 -c :qa!
==27959==
==27959== Conditional jump or move depends on uninitialised value(s)
==27959== at 0x4C34D08: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27959== by 0x38774F: msg_outtrans_attr (message.c:1551)
==27959== by 0x387B03: msg_attr_keep (message.c:176)
==27959== by 0x387F73: msg_attr (message.c:123)
==27959== by 0x387F73: msg_trunc_attr (message.c:933)
==27959== by 0x1FE1B4: process_next_cpt_value (insexpand.c:3271)
==27959== by 0x1FE1B4: ins_compl_get_exp (insexpand.c:3743)
==27959== by 0x1FE1B4: find_next_completion_match (insexpand.c:3992)
==27959== by 0x1FE1B4: ins_compl_next (insexpand.c:4093)
==27959== by 0x1FE72A: ins_complete (insexpand.c:4944)
==27959== by 0x180426: edit (edit.c:1281)
==27959== by 0x22F599: invoke_edit.isra.1 (normal.c:7035)
==27959== by 0x2317D1: n_opencmd (normal.c:6279)
==27959== by 0x2317D1: nv_open (normal.c:7416)
==27959== by 0x2385B4: normal_cmd (normal.c:939)
==27959== by 0x1B671C: exec_normal (ex_docmd.c:8807)
==27959== by 0x1B697F: ex_normal (ex_docmd.c:8693)
==27959==
==27959==
==27959== HEAP SUMMARY:
==27959== in use at exit: 73,438 bytes in 382 blocks
==27959== total heap usage: 1,227 allocs, 845 frees, 416,543 bytes allocated
==27959==
==27959== LEAK SUMMARY:
==27959== definitely lost: 0 bytes in 0 blocks
==27959== indirectly lost: 0 bytes in 0 blocks
==27959== possibly lost: 139 bytes in 8 blocks
==27959== still reachable: 73,299 bytes in 374 blocks
==27959== suppressed: 0 bytes in 0 blocks
==27959== Rerun with --leak-check=full to see details of leaked memory
==27959==
==27959== For counts of detected and suppressed errors, rerun with: -v
==27959== Use --track-origins=yes to see where uninitialised values come from
==27959== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
But if width = 201, and height = 10, it doesn't:
guest@elk:~/trung$ stty size
10 201
guest@elk:~/trung$ valgrind ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S ./poc_vim01 -c ':qa!'
==28333== Memcheck, a memory error detector
==28333== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28333== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28333== Command: ./vim2/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S ./poc_vim01 -c :qa!
==28333==
==28333==
==28333== HEAP SUMMARY:
==28333== in use at exit: 73,438 bytes in 382 blocks
==28333== total heap usage: 1,227 allocs, 845 frees, 416,543 bytes allocated
==28333==
==28333== LEAK SUMMARY:
==28333== definitely lost: 0 bytes in 0 blocks
==28333== indirectly lost: 0 bytes in 0 blocks
==28333== possibly lost: 139 bytes in 8 blocks
==28333== still reachable: 73,299 bytes in 374 blocks
==28333== suppressed: 0 bytes in 0 blocks
==28333== Rerun with --leak-check=full to see details of leaked memory
==28333==
==28333== For counts of detected and suppressed errors, rerun with: -v
==28333== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
You can use this command to print out all the variables at this line:
gdb -ex "b msg_may_trunc" -ex "r" -ex "printf \"Rows=%d %c\", Rows,0xA" -ex "printf \"Columns=%d %c\", Columns,0xA" -ex "printf \"cmdline_row=%d %c\", cmdline_row,0xA" -ex "printf \"sc_col=%d %c\", sc_col,0xA" --args ./vim/src/vim -u NONE -i NONE -n -m -X -Z -e -s -S ./poc_vim01 -c ':qa!'
My output which causes crash:
Rows=2
Columns=12
cmdline_row=51
sc_col=209
With this, room
will be 0xfffffe78
finally I can reproduce it. Thanks for being persistant.