Summary
Selecting text in glass and dragging it to another window (which triggers a SelectionRequest) causes a segfault.
Steps to reproduce
- Open glass with any shell.
- Select any text with the mouse.
- Drag / paste it into another window.
Crash details
Segmentation fault glass
glass[341666]: segfault at 21b7004 ip 00000000004090ae sp 00007ffe7eb5a310 error 4 in glass[90ae,401000+12000]
Code: 00 00 48 6b c0 10 48 8d 98 20 cd a4 01 4d 39 f5 0f 8d 54 01 00 00 49 81 ff fc 3f 00
00 0f 8d 8e 01 00 00 4c 89 ea 48 6b d2 10 <f6> 44 13 04 08 74 18 0f b7 4c 13 06 81
f9 00 04 00 00 73 0b 8b 04
error 4 = page-not-present user-mode read. The faulting address 0x21b7004 is past the end of the grid buffer.
Decoded instruction sequence at crash site
imul rax, rax, 16 ; rax = row_index * 16 (actually row * MAX_COLS*CELL_SIZE computed earlier)
lea rbx, [rax + 0x1a4cd20] ; rbx = &grid[row]
cmp r13, r14 ; bounds check: col vs grid_cols ✓
jge .skip
cmp r15, 0x3ffc ; bounds check: sel_buf output index vs 16380 ✓
jge .done
mov rdx, r13
imul rdx, rdx, 16 ; rdx = col * CELL_SIZE
test byte [rbx + rdx + 0x4], 0x08 ; ← SEGFAULT: rbx is past grid end
Root cause
selection_extract (line ~11533) explicitly allows sel_start_row/sel_end_row to exceed MAX_ROWS - 1 (127) during scrollback selection (see comment at line ~11440):
"Let sel_start_row grow past grid_rows-1; selection_extract's .se_row_grid_shifted path maps r12 → live[r12 - scroll_offset] which stays in bounds because we increment scroll_offset and sel_start_row in lockstep."
The invariant holds while scroll_offset is still set. But when the user drags the selection to another window, the SelectionRequest arrives after the button release. By that point scroll_offset may have been reset to 0 (e.g. by snapping back to the bottom of the viewport). The .se_row_live path is then taken:
.se_row_live:
mov rax, r12
imul rax, MAX_COLS
imul rax, CELL_SIZE
lea rbx, [grid + rax] ; r12 >= MAX_ROWS → out of bounds
The two row-bounds checks in the extracted loop (cmp r12, [sel_end_row] and cmp r15, 0x3ffc) guard against overrunning sel_buf, but neither prevents computing an rbx that already points outside grid.
Suggested fix
In selection_extract, after resolving rbx via .se_row_live, add a hard clamp:
.se_row_live:
mov rax, r12
cmp rax, MAX_ROWS ; clamp row to valid grid range
jge .se_done
imul rax, MAX_COLS
imul rax, CELL_SIZE
lea rbx, [grid + rax]
Similarly for .se_row_grid_shifted, verify r12 - scroll_offset is in [0, MAX_ROWS) before indexing.
Summary
Selecting text in glass and dragging it to another window (which triggers a
SelectionRequest) causes a segfault.Steps to reproduce
Crash details
error 4= page-not-present user-mode read. The faulting address0x21b7004is past the end of thegridbuffer.Decoded instruction sequence at crash site
Root cause
selection_extract(line ~11533) explicitly allowssel_start_row/sel_end_rowto exceedMAX_ROWS - 1(127) during scrollback selection (see comment at line ~11440):The invariant holds while
scroll_offsetis still set. But when the user drags the selection to another window, theSelectionRequestarrives after the button release. By that pointscroll_offsetmay have been reset to 0 (e.g. by snapping back to the bottom of the viewport). The.se_row_livepath is then taken:The two row-bounds checks in the extracted loop (
cmp r12, [sel_end_row]andcmp r15, 0x3ffc) guard against overrunningsel_buf, but neither prevents computing anrbxthat already points outsidegrid.Suggested fix
In
selection_extract, after resolvingrbxvia.se_row_live, add a hard clamp:Similarly for
.se_row_grid_shifted, verifyr12 - scroll_offsetis in[0, MAX_ROWS)before indexing.