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

unclamped destination column crashes foot #2352

Closed
opened 2026年05月21日 14:57:59 +02:00 by jackoftrade · 0 comments

Foot Version

foot 1.27.0

TERM environment variable

foot

Compositor Name and Version

sway 1.11

Distribution

arch

Terminal multiplexer

No response

Shell, TUI, application

No response

Server/standalone mode

  • Standalone
  • Server

Foot config

default

Description of Bug and Steps to Reproduce

The DECCRA handler in csi.c (case 'v', CSI ... $ v) computes:

int dst_left = vt_param_get(term, 6, 1) - 1; // not clamped
int dst_right = min(dst_left + (src_right - src_left), term->cols - 1);
const size_t cell_count = min(src_right - src_left,
dst_right - dst_left) + 1;
...
copy[r] = xmalloc(cell_count * sizeof(copy[r][0]));
...
struct cell *cell = &row->cells[dst_left];
memcpy(cell, copy[r], cell_count * sizeof(copy[r][0]));

The source rect is clamped via params_to_rectangular_area() and
dst_right is clamped to cols-1, but dst_left itself is never clamped.
If the parameter makes dst_left >= cols, dst_right - dst_left is
negative; cell_count is then computed as a non-positive int and
converted to size_t, becoming near SIZE_MAX. xmalloc gets a
SIZE_MAX-class request, fails, and aborts via the fatal-error path.
&row->cells[dst_left] is also out of bounds.

The sibling rectangular ops DECFRA ('x'), DECERA ('z') and DECSERA
('{') all route their rectangle through params_to_rectangular_area()
and are fine; DECCRA is the only one that takes dst_left straight from
a parameter.

DECCRA is unconditionally enabled (no tweak/security flag). Any byte
stream the parser reads can trigger this - terminal output, an SSH
banner, cat of a crafted file, output of a network tool, etc. One
escape sequence kills foot (and every program running in that window).

Reproduce (default grid is wider than 80; any param 6 value > cols+1
works):

printf '033円[1;1;1;1;1;1;300;1$v'

Fix: clamp dst_left to [0, term->cols - 1] (and reject the sequence if
the destination column is outside the grid), the same way
params_to_rectangular_area() clamps the source. Additionally, validate
row_count and cell_count as signed before converting to size_t so a
negative value cannot become a huge allocation.

Relevant logs, stacktraces, etc.

Debug log (full real VT pipeline,
fdm_ptmx -> vt_from_slave -> csi_dispatch):

src(t=0,l=0,b=0,r=0) dst_left=299 dst_right=134 row_count=1
cell_count=18446744073709551452 cols=135

==ERROR== requested allocation size 0xfffffffffffff850 exceeds maximum
#1 xmalloc
#2 csi_dispatch
#3 vt_from_slave
#4 fdm_ptmx

### Foot Version foot 1.27.0 ### TERM environment variable foot ### Compositor Name and Version sway 1.11 ### Distribution arch ### Terminal multiplexer _No response_ ### Shell, TUI, application _No response_ ### Server/standalone mode - [ ] Standalone - [ ] Server ### Foot config ```ini default ``` ### Description of Bug and Steps to Reproduce The DECCRA handler in csi.c (case 'v', CSI ... $ v) computes: int dst_left = vt_param_get(term, 6, 1) - 1; // not clamped int dst_right = min(dst_left + (src_right - src_left), term->cols - 1); const size_t cell_count = min(src_right - src_left, dst_right - dst_left) + 1; ... copy[r] = xmalloc(cell_count * sizeof(copy[r][0])); ... struct cell *cell = &row->cells[dst_left]; memcpy(cell, copy[r], cell_count * sizeof(copy[r][0])); The source rect is clamped via params_to_rectangular_area() and dst_right is clamped to cols-1, but dst_left itself is never clamped. If the parameter makes dst_left >= cols, dst_right - dst_left is negative; cell_count is then computed as a non-positive int and converted to size_t, becoming near SIZE_MAX. xmalloc gets a SIZE_MAX-class request, fails, and aborts via the fatal-error path. &row->cells[dst_left] is also out of bounds. The sibling rectangular ops DECFRA ('x'), DECERA ('z') and DECSERA ('{') all route their rectangle through params_to_rectangular_area() and are fine; DECCRA is the only one that takes dst_left straight from a parameter. DECCRA is unconditionally enabled (no tweak/security flag). Any byte stream the parser reads can trigger this - terminal output, an SSH banner, cat of a crafted file, output of a network tool, etc. One escape sequence kills foot (and every program running in that window). Reproduce (default grid is wider than 80; any param 6 value > cols+1 works): printf '033円[1;1;1;1;1;1;300;1$v' Fix: clamp dst_left to [0, term->cols - 1] (and reject the sequence if the destination column is outside the grid), the same way params_to_rectangular_area() clamps the source. Additionally, validate row_count and cell_count as signed before converting to size_t so a negative value cannot become a huge allocation. ### Relevant logs, stacktraces, etc. Debug log (full real VT pipeline, fdm_ptmx -> vt_from_slave -> csi_dispatch): src(t=0,l=0,b=0,r=0) dst_left=299 dst_right=134 row_count=1 cell_count=18446744073709551452 cols=135 ==ERROR== requested allocation size 0xfffffffffffff850 exceeds maximum #1 xmalloc #2 csi_dispatch #3 vt_from_slave #4 fdm_ptmx
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
1 participant
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#2352
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?