Bug 278579 - nvi can malfunction if one types invalid UTF-8
Summary: nvi can malfunction if one types invalid UTF-8
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-25 13:43 UTC by Robert Morris
Modified: 2024-04-25 22:49 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Morris 2024-04-25 13:43:38 UTC
If LANG is set to C.UTF-8, then typing illegal UTF-8 in nvi can cause
v_event_get() to access elements in gp->i_event[] even though
gp->i_cnt is zero -- that is, elements that have not been properly
set.

Here's how this can happen. v_event_get() calls gp->scr_event(), which
is cl_event(). If the input is bad UTF-8, cl_event() sets evp->e_event
to E_STRING, evp->e_len to zero, and returns zero (no error).
v_event_get() calls v_event_append(), but since e_len is zero, nothing
is put in gp->i_event[] and gp->i_cnt is not incremented. But the code
goes on to use gp->i_event[gp->i_next], even though that element
wasn't set.

Another consequence is that v_event_get() calls QREM(1) before returning
(line 670 of common/key.c), but since i_cnt was likely zero, QREM()'s
decrement may wrap i_cnt to a huge unsigned.

Since i_cnt can now incorrectly be > 0, v_key()'s next call to
v_event_get() can incorrectly return whatever happened to be in
gp->i_event[0], and if it's not valid, the abort() in v_event_err()
may be called.

You can see the abort() by setting LANG to C.UTF-8, running
nvi, and typing a pair of characters with high bits set that
aren't legal utf8. On my keyboard, I can type option-u option-i,
which generates 0xf5 0xe9.

Perhaps this can be fixed by 1) goto retry in v_event_get() if
gp->scr_event() returns an E_STRING with e_len == 0, and 2) set
clp->skip = 0 in cl_event() on Invalid input, to reset the UTF-8
parsing state. But I do not understand the code well enough to be
sure.