Skip to content

fix segmentation fault in tabline format parser#9800

Closed
brandon1024 wants to merge 1 commit into
vim:masterfrom
brandon1024:tl-segflt-off-by-one
Closed

fix segmentation fault in tabline format parser#9800
brandon1024 wants to merge 1 commit into
vim:masterfrom
brandon1024:tl-segflt-off-by-one

Conversation

@brandon1024

Copy link
Copy Markdown
Contributor

When parsing the statusline/tabline format string, highlight information
is stored in an array which has size 20 by default. The last item in
this array is used to indicate the end of the array, with struct members
being set to NULL/0.

When there are exactly 20 highlight items in the format string, the
array is not resized to account for the last item used to indicate the
end of the array. When copying the items to an array to be passed back
to the caller, the routine attempts to write beyond the size of the
array, often resulting in a segmentation fault.

To address this, update parser to allocate one more entry in the array
to account for the array end indicator. A test was introduced that
validates the fix when tests are run with valgrind memcheck.

@codecov

codecov Bot commented Feb 18, 2022

Copy link
Copy Markdown

Codecov Report

Merging #9800 (6d5139a) into master (e89bfd2) will decrease coverage by 0.16%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #9800      +/-   ##
==========================================
- Coverage   81.76%   81.59%   -0.17%     
==========================================
  Files         167      167              
  Lines      186400   186400              
  Branches    42020    42020              
==========================================
- Hits       152403   152089     -314     
- Misses      21599    21885     +286     
- Partials    12398    12426      +28     
Flag Coverage Δ
huge-clang-none 82.15% <100.00%> (-0.01%) ⬇️
huge-gcc-none 82.50% <100.00%> (-0.01%) ⬇️
huge-gcc-testgui ?
huge-gcc-unittests 2.02% <0.00%> (ø)
linux 83.44% <100.00%> (-0.32%) ⬇️
mingw-x64-HUGE 0.00% <0.00%> (ø)
mingw-x64-HUGE-gui 77.00% <100.00%> (+<0.01%) ⬆️
windows 75.78% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/buffer.c 86.43% <100.00%> (-0.27%) ⬇️
src/gui_gtk_x11.c 51.59% <0.00%> (-5.48%) ⬇️
src/gui_gtk.c 24.23% <0.00%> (-3.75%) ⬇️
src/libvterm/src/encoding.c 73.52% <0.00%> (-1.97%) ⬇️
src/hardcopy.c 77.49% <0.00%> (-1.62%) ⬇️
src/gui_xim.c 22.38% <0.00%> (-1.20%) ⬇️
src/os_unix.c 67.35% <0.00%> (-1.08%) ⬇️
src/gui.c 73.25% <0.00%> (-0.88%) ⬇️
src/highlight.c 81.25% <0.00%> (-0.83%) ⬇️
src/gui_beval.c 54.58% <0.00%> (-0.80%) ⬇️
... and 29 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e89bfd2...6d5139a. Read the comment docs.

@brandon1024

Copy link
Copy Markdown
Contributor Author

Here is the output from Valgrind, before the fix:

Details
==19611== Memcheck, a memory error detector
==19611== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19611== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==19611== Command: /home/brandon/dev/other/vim/src/vim --clean
==19611== Parent PID: 18457
==19611== 
==19611== Invalid write of size 8
==19611==    at 0x15C2A3: build_stl_str_hl (buffer.c:5034)
==19611==    by 0x2F4BA3: win_redr_custom (screen.c:1322)
==19611==    by 0x2FAA36: draw_tabline (screen.c:4436)
==19611==    by 0x18E8EB: update_screen (drawscreen.c:259)
==19611==    by 0x41A9FE: main_loop (main.c:1401)
==19611==    by 0x419F3D: vim_main2 (main.c:877)
==19611==    by 0x41963B: main (main.c:424)
==19611==  Address 0x6f1aa00 is 0 bytes after a block of size 320 alloc'd
==19611==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==19611==    by 0x149EC0: lalloc (alloc.c:248)
==19611==    by 0x149D73: alloc (alloc.c:151)
==19611==    by 0x15956F: build_stl_str_hl (buffer.c:4173)
==19611==    by 0x2F4BA3: win_redr_custom (screen.c:1322)
==19611==    by 0x2FAA36: draw_tabline (screen.c:4436)
==19611==    by 0x18E8EB: update_screen (drawscreen.c:259)
==19611==    by 0x41A9FE: main_loop (main.c:1401)
==19611==    by 0x419F3D: vim_main2 (main.c:877)
==19611==    by 0x41963B: main (main.c:424)
==19611== 
==19611== Invalid write of size 4
==19611==    at 0x15C2B1: build_stl_str_hl (buffer.c:5035)
==19611==    by 0x2F4BA3: win_redr_custom (screen.c:1322)
==19611==    by 0x2FAA36: draw_tabline (screen.c:4436)
==19611==    by 0x18E8EB: update_screen (drawscreen.c:259)
==19611==    by 0x41A9FE: main_loop (main.c:1401)
==19611==    by 0x419F3D: vim_main2 (main.c:877)
==19611==    by 0x41963B: main (main.c:424)
==19611==  Address 0x6f1aa08 is 8 bytes after a block of size 320 alloc'd
==19611==    at 0x483877F: malloc (vg_replace_malloc.c:307)
==19611==    by 0x149EC0: lalloc (alloc.c:248)
==19611==    by 0x149D73: alloc (alloc.c:151)
==19611==    by 0x15956F: build_stl_str_hl (buffer.c:4173)
==19611==    by 0x2F4BA3: win_redr_custom (screen.c:1322)
==19611==    by 0x2FAA36: draw_tabline (screen.c:4436)
==19611==    by 0x18E8EB: update_screen (drawscreen.c:259)
==19611==    by 0x41A9FE: main_loop (main.c:1401)
==19611==    by 0x419F3D: vim_main2 (main.c:877)
==19611==    by 0x41963B: main (main.c:424)
...

With these changes applied, these invalid writes are no longer present in the Valgrind output.

When parsing the statusline/tabline format string, highlight information
is stored in an array which has size 20 by default. The last item in
this array is used to indicate the end of the array, with struct members
being set to NULL/0.

When there are exactly 20 highlight items in the format string, the
array is not resized to account for the last item used to indicate the
end of the array. When copying the items to an array to be passed back
to the caller, the routine attempts to write beyond the size of the
array, often resulting in a segmentation fault.

To address this, update parser to allocate one more entry in the array
to account for the array end indicator. A test was introduced that
validates the fix when tests are run with valgrind memcheck.
@brammool brammool closed this in a493b65 Feb 19, 2022
@brandon1024
brandon1024 deleted the tl-segflt-off-by-one branch February 19, 2022 12:57
seandewar added a commit to seandewar/neovim that referenced this pull request Feb 19, 2022
Problem:    Illegal memory access when using exactly 20 highlights.
Solution:   Add one more item in the array. (Brandon Richardson,
            closes vim/vim#9800)
vim/vim@a493b65
seandewar added a commit to seandewar/neovim that referenced this pull request Feb 19, 2022
Problem:    Illegal memory access when using exactly 20 highlights.
Solution:   Add one more item in the array. (Brandon Richardson,
            closes vim/vim#9800)
vim/vim@a493b65
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant