Buffer overflow in handle_input() — src/tty_interface.c line 334
Summary: strcat(state->input, s) in handle_input() appends terminal input to a fixed 32-byte buffer without bounds checking. Accumulated input that exceeds 32 bytes overflows into the adjacent exit field in tty_interface_t, causing forced silent termination. The struct is stack-allocated, so further overflow reaches the stack frame.
Location
src/tty_interface.c, function handle_input(), line 334:
Root cause
state->input is declared as char input[32] in tty_interface_t (tty_interface.h line 24). handle_input() accumulates terminal input across calls — appending each chunk until a complete keybinding is matched, then resetting with strcpy(input, ""). There is no check that the accumulated content fits within the 32-byte buffer before strcat is called.
Struct layout
typedef struct {
tty_t *tty;
choices_t *choices;
options_t *options;
char search[SEARCH_SIZE_MAX + 1];
char last_search[SEARCH_SIZE_MAX + 1];
size_t cursor;
int ambiguous_key_pending;
char input[32]; /* ← overflow origin */
int exit; /* ← first field overwritten */
} tty_interface_t;
The struct is stack-allocated in fzy.c line 63: tty_interface_t tty_interface;
Impact
Confirmed: Overflow into the adjacent exit int field causes tty_interface_run() to terminate its loop — forced silent exit of fzy. A shell pipeline using fzy breaks silently when this is triggered.
Plausible: The struct is stack-allocated. Overflow past exit reaches the stack frame. Exploitability depends on build mitigations.
Exploitation requirement: Attacker must supply terminal input to fzy — requires local access or control of a terminal session running fzy.
Suggested fix
Replace strcat with a bounds-checked equivalent:
/* Before */
strcat(state->input, s);
/* After */
strncat(state->input, s, sizeof(state->input) - strlen(state->input) - 1);
A belt-and-suspenders version that makes the constraint explicit:
size_t remaining = sizeof(state->input) - strlen(state->input) - 1;
if (remaining > 0) {
strncat(state->input, s, remaining);
}
How this was found
This finding was produced by an ensemble divergence code scanner applying the Intent Scanner (does/says gap analysis) to fzy's source. The finding was Haiku-exclusive on the cold run — not confirmed by Sonnet — and has been manually verified against the source. The struct layout, buffer size, and stack allocation were confirmed by direct inspection.
Happy to provide additional detail or test a patch. Thank you for maintaining fzy.
Buffer overflow in handle_input() — src/tty_interface.c line 334
Summary:
strcat(state->input, s)inhandle_input()appends terminal input to a fixed 32-byte buffer without bounds checking. Accumulated input that exceeds 32 bytes overflows into the adjacentexitfield intty_interface_t, causing forced silent termination. The struct is stack-allocated, so further overflow reaches the stack frame.Location
src/tty_interface.c, functionhandle_input(), line 334:Root cause
state->inputis declared aschar input[32]intty_interface_t(tty_interface.h line 24).handle_input()accumulates terminal input across calls — appending each chunk until a complete keybinding is matched, then resetting withstrcpy(input, ""). There is no check that the accumulated content fits within the 32-byte buffer beforestrcatis called.Struct layout
The struct is stack-allocated in
fzy.cline 63:tty_interface_t tty_interface;Impact
Confirmed: Overflow into the adjacent
exitint field causestty_interface_run()to terminate its loop — forced silent exit of fzy. A shell pipeline using fzy breaks silently when this is triggered.Plausible: The struct is stack-allocated. Overflow past
exitreaches the stack frame. Exploitability depends on build mitigations.Exploitation requirement: Attacker must supply terminal input to fzy — requires local access or control of a terminal session running fzy.
Suggested fix
Replace
strcatwith a bounds-checked equivalent:A belt-and-suspenders version that makes the constraint explicit:
How this was found
This finding was produced by an ensemble divergence code scanner applying the Intent Scanner (does/says gap analysis) to fzy's source. The finding was Haiku-exclusive on the cold run — not confirmed by Sonnet — and has been manually verified against the source. The struct layout, buffer size, and stack allocation were confirmed by direct inspection.
Happy to provide additional detail or test a patch. Thank you for maintaining fzy.