mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-22 05:02:31 +00:00
Text sizing protocol: Fix a buffer overflow
When a natural width (no explicit ``w`` key) text sizing escape code contains a grapheme cluster longer than four codepoints
This commit is contained in:
parent
5f04193347
commit
7d2fbaadcc
3 changed files with 22 additions and 2 deletions
|
|
@ -253,6 +253,8 @@ Detailed list of changes
|
|||
|
||||
- Drag and drop protocol: deny requests for drag data made before the user has actually dropped something onto the window
|
||||
|
||||
- Text sizing protocol: Fix a buffer overflow when a natural width (no explicit ``w`` key) text sizing escape code contains a grapheme cluster longer than four codepoints
|
||||
|
||||
|
||||
0.48.2 [2026-07-30]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -1619,8 +1619,10 @@ screen_handle_multicell_command(Screen *self, const MultiCellCommand *cmd, const
|
|||
char_type ch = self->lc->chars[i];
|
||||
CharProps cp = char_props_for(ch);
|
||||
if (cp.is_invalid) continue;
|
||||
if ((s = grapheme_segmentation_step(s, cp)).add_to_current_cell || (wcwidth_std(cp) == 0 && lc.count)) lc.chars[lc.count++] = ch;
|
||||
else {
|
||||
if ((s = grapheme_segmentation_step(s, cp)).add_to_current_cell || (wcwidth_std(cp) == 0 && lc.count)) {
|
||||
ensure_space_for_chars(&lc, lc.count + 1);
|
||||
lc.chars[lc.count++] = ch;
|
||||
} else {
|
||||
if (lc.count) handle_variable_width_multicell_command(self, mcd, &lc);
|
||||
switch (wcwidth_std(cp)) {
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -150,6 +150,22 @@ def test_multicell(self: TestMulticell) -> None:
|
|||
for x in range(1, 3):
|
||||
comb(x, y)
|
||||
comb(0, 1)
|
||||
|
||||
# Regression test for buffer overflow when a natural width (w=0) grapheme
|
||||
# cluster is longer than the ListOfChars stack buffer. See the accumulation
|
||||
# loop in screen_handle_multicell_command(). The cluster is accumulated in
|
||||
# full (overflowing the buffer before the fix) even though the text stored
|
||||
# per cell is later capped at MAX_NUM_CODEPOINTS_PER_CELL (24).
|
||||
capped = 'a' + '́' * 23
|
||||
s.reset()
|
||||
multicell(s, 'a' + '́' * 32)
|
||||
ac(0, 0, is_multicell=True, width=1, scale=1, x=0, y=0, text=capped, natural_width=True)
|
||||
# A second, even longer cluster exercises the heap-backed buffer after the first flush.
|
||||
s.reset()
|
||||
multicell(s, 'a' + '́' * 32 + 'b' + '́' * 48)
|
||||
ac(0, 0, is_multicell=True, x=0, y=0, text=capped, natural_width=True)
|
||||
ac(1, 0, is_multicell=True, x=0, y=0, text='b' + '́' * 23, natural_width=True)
|
||||
|
||||
s.reset()
|
||||
multicell(s, 'aüa', scale=2)
|
||||
self.ae(s.cursor.x, 6)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue