dnkl/foot
41
2.0k
Fork
You've already forked foot
242

Crash in csi_dispatch #522

Closed
opened 2021年05月16日 14:04:02 +02:00 by Amanieu · 3 comments

I noticed this when accidentally cating an executable file.

Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007efdbd8bb687 in __memmove_avx_unaligned_erms () from /usr/lib/libc.so.6
#1 0x000055a4c71922a9 in csi_dispatch (term=0x55a4c8c276f0, final=<optimized out>) at ../csi.c:1065
#2 0x000055a4c71902f0 in action_csi_dispatch (c=<optimized out>, term=0x55a4c8c276f0) at ../vt.c:499
#3 state_csi_param_switch (data=<optimized out>, term=0x55a4c8c276f0) at ../vt.c:887
#4 vt_from_slave (term=term@entry=0x55a4c8c276f0, data=data@entry=0x7ffde003fab0 "234円067円", len=<optimized out>) at ../vt.c:1144
#5 0x000055a4c7183981 in fdm_ptmx (fdm=0x55a4c8bb5a60, fd=6, events=<optimized out>, data=0x55a4c8c276f0) at ../terminal.c:255
#6 0x000055a4c716327b in fdm_poll (fdm=fdm@entry=0x55a4c8bb5a60) at ../fdm.c:459
#7 0x000055a4c715a1f7 in main (argc=<optimized out>, argv=<optimized out>) at ../main.c:535

Here is the relevant code in csi_dispatch:

 case 'P': {
 /* DCH: Delete character(s) */
 /* Number of characters to delete */
 int count = min(
 vt_param_get(term, 0, 1), term->cols - term->grid->cursor.point.col);
 /* Number of characters left after deletion (on current line) */
 int remaining = term->cols - (term->grid->cursor.point.col + count);
 /* 'Delete' characters by moving the remaining ones */
 memmove(&term->grid->cur_row->cells[term->grid->cursor.point.col],
 &term->grid->cur_row->cells[term->grid->cursor.point.col + count],
 remaining * sizeof(term->grid->cur_row->cells[0]));
 for (size_t c = 0; c < remaining; c++)
 term->grid->cur_row->cells[term->grid->cursor.point.col + c].attrs.clean = 0;
 term->grid->cur_row->dirty = true;
 /* Erase the remainder of the line */
 term_erase(
 term,
 &(struct coord){term->grid->cursor.point.col + remaining, term->grid->cursor.point.row},
 &(struct coord){term->cols - 1, term->grid->cursor.point.row});
 term->grid->cursor.lcf = false;
 break;
 }

The crash happens because count is -966033864: min treats its inputs as signed numbers and vt_param_get(term, 0, 1) returned -966033864.

I noticed this when accidentally `cat`ing an executable file. ``` Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00007efdbd8bb687 in __memmove_avx_unaligned_erms () from /usr/lib/libc.so.6 #1 0x000055a4c71922a9 in csi_dispatch (term=0x55a4c8c276f0, final=<optimized out>) at ../csi.c:1065 #2 0x000055a4c71902f0 in action_csi_dispatch (c=<optimized out>, term=0x55a4c8c276f0) at ../vt.c:499 #3 state_csi_param_switch (data=<optimized out>, term=0x55a4c8c276f0) at ../vt.c:887 #4 vt_from_slave (term=term@entry=0x55a4c8c276f0, data=data@entry=0x7ffde003fab0 "234円067円", len=<optimized out>) at ../vt.c:1144 #5 0x000055a4c7183981 in fdm_ptmx (fdm=0x55a4c8bb5a60, fd=6, events=<optimized out>, data=0x55a4c8c276f0) at ../terminal.c:255 #6 0x000055a4c716327b in fdm_poll (fdm=fdm@entry=0x55a4c8bb5a60) at ../fdm.c:459 #7 0x000055a4c715a1f7 in main (argc=<optimized out>, argv=<optimized out>) at ../main.c:535 ``` Here is the relevant code in `csi_dispatch`: ```c case 'P': { /* DCH: Delete character(s) */ /* Number of characters to delete */ int count = min( vt_param_get(term, 0, 1), term->cols - term->grid->cursor.point.col); /* Number of characters left after deletion (on current line) */ int remaining = term->cols - (term->grid->cursor.point.col + count); /* 'Delete' characters by moving the remaining ones */ memmove(&term->grid->cur_row->cells[term->grid->cursor.point.col], &term->grid->cur_row->cells[term->grid->cursor.point.col + count], remaining * sizeof(term->grid->cur_row->cells[0])); for (size_t c = 0; c < remaining; c++) term->grid->cur_row->cells[term->grid->cursor.point.col + c].attrs.clean = 0; term->grid->cur_row->dirty = true; /* Erase the remainder of the line */ term_erase( term, &(struct coord){term->grid->cursor.point.col + remaining, term->grid->cursor.point.row}, &(struct coord){term->cols - 1, term->grid->cursor.point.row}); term->grid->cursor.lcf = false; break; } ``` The crash happens because `count` is `-966033864`: `min` treats its inputs as signed numbers and `vt_param_get(term, 0, 1)` returned `-966033864`.
Collaborator
Copy link

It looks like the negative value is coming from the implicit unsigned -> int conversion in vt_param_get(). All the uses of int in that function should probably be changed to unsigned, since that's what type vt_param::value is and valid CSI params can't be negative.

Reproducer:

printf "033円[4294967295P"
It looks like the negative value is coming from the implicit `unsigned` -> `int` conversion in `vt_param_get()`. All the uses of `int` in that function should probably be changed to `unsigned`, since that's what type `vt_param::value` is and valid CSI params can't be negative. Reproducer: ```sh printf "033円[4294967295P" ```
Owner
Copy link

All the uses of int in that function should probably be changed to unsigned, since that's what type vt_param::value is and valid CSI params can't be negative.

@craigbarnes I agree competely. This is pretty bad design...

But, it appears all uses of vt_param_get() assigns to signed int. This of course needs to be changed as well.

There may be places where negative values are valid intermediate values.

> All the uses of int in that function should probably be changed to unsigned, since that's what type vt_param::value is and valid CSI params can't be negative. @craigbarnes I agree competely. This is pretty bad design... But, it appears all **uses** of `vt_param_get()` assigns to `signed int`. This of course needs to be changed as well. There _may_ be places where negative values are valid intermediate values.
Owner
Copy link

Change of plan; we regularly do signed arithmetic, meaning we want vt_param_get() to return an int.

What we'll do instead is limit parameter values to INT_MAX.

Change of plan; we regularly do signed arithmetic, meaning we _want_ `vt_param_get()` to return an `int`. What we'll do instead is limit parameter values to `INT_MAX`.
Sign in to join this conversation.
No Branch/Tag specified
master
osc-5522
sixel-heap-buffer-overflow
releases/1.27
releases/1.26
releases/1.25
releases/1.24
multi-cursor
releases/1.23
pixman-16f-2
releases/1.22
releases/1.21
releases/1.20
releases/1.19
releases/1.18
releases/1.17
releases/1.16
releases/1.15
releases/1.14
releases/1.13
releases/1.12
releases/1.11
releases/1.10
releases/1.9
releases/1.8
releases/1.7
releases/1.6
releases/1.5
releases/1.4
releases/1.3
releases/1.2
releases/1.1
releases/1.0
1.27.0
1.26.1
1.26.0
1.25.0
1.24.0
1.23.1
1.23.0
1.22.3
1.22.2
1.22.1
1.22.0
1.21.0
1.20.2
1.20.1
1.20.0
1.19.0
1.18.1
1.18.0
1.17.2
1.17.1
1.17.0
1.16.2
1.16.1
1.16.0
1.15.3
1.15.2
1.15.1
1.15.0
1.14.0
1.13.1
1.13.0
1.12.1
1.12.0
1.11.0
1.10.3
1.10.2
1.10.1
1.10.0
1.9.2
1.9.1
1.9.0
1.8.2
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.3
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
0.9.0
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dnkl/foot#522
Reference in a new issue
dnkl/foot
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?