tty: n_tty: Fix buffer offsets when lookahead is used

commit b19ab7ee2c4c1ec5f27c18413c3ab63907f7d55c upstream.

When lookahead has "consumed" some characters (la_count > 0),
n_tty_receive_buf_standard() and n_tty_receive_buf_closing() for
characters beyond the la_count are given wrong cp/fp offsets which
leads to duplicating and losing some characters.

If la_count > 0, correct buffer pointers and make count consistent too
(the latter is not strictly necessary to fix the issue but seems more
logical to adjust all variables immediately to keep state consistent).

Reported-by: Vadym Krevs <vkrevs@yahoo.com>
Fixes: 6bb6fa6908eb ("tty: Implement lookahead to process XON/XOFF timely")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218834
Tested-by: Vadym Krevs <vkrevs@yahoo.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20240514140429.12087-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ilpo Järvinen 2024-05-14 17:04:29 +03:00 committed by Greg Kroah-Hartman
parent 185a1b1fcc
commit 03f916e56a

View File

@ -1602,15 +1602,25 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
else if (ldata->raw || (L_EXTPROC(tty) && !preops))
n_tty_receive_buf_raw(tty, cp, fp, count);
else if (tty->closing && !L_EXTPROC(tty)) {
if (la_count > 0)
if (la_count > 0) {
n_tty_receive_buf_closing(tty, cp, fp, la_count, true);
if (count > la_count)
n_tty_receive_buf_closing(tty, cp, fp, count - la_count, false);
cp += la_count;
if (fp)
fp += la_count;
count -= la_count;
}
if (count > 0)
n_tty_receive_buf_closing(tty, cp, fp, count, false);
} else {
if (la_count > 0)
if (la_count > 0) {
n_tty_receive_buf_standard(tty, cp, fp, la_count, true);
if (count > la_count)
n_tty_receive_buf_standard(tty, cp, fp, count - la_count, false);
cp += la_count;
if (fp)
fp += la_count;
count -= la_count;
}
if (count > 0)
n_tty_receive_buf_standard(tty, cp, fp, count, false);
flush_echoes(tty);
if (tty->ops->flush_chars)