This commit fixes a bug that causes incorrect results when pasting more than 32 bytes, the size of the receive buffer b->buffer, into the virtio console.
Example (note that the last 32 bytes are always correct, but something goes wrong just before the last 32 bytes): Pasting abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*() Received abcdefg)EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()EFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*() The root cause of this bug is as follows: The mux_chr_read function passes the data to the backend via be->chr_read one byte at a time, either directly or via another mux_chr_accept_input method. However, if the receive buffer is full, there is a chance that the mux_chr_can_read method will return more than one byte, because in this case the method directly returns whatever be->chr_can_read returns. This is problematic because if mux_chr_read passes a byte to the backend by calling be->chr_read, it will consume the entire backend buffer, at least in the case of virtio. Once all backend buffers are used, mux_chr_read writes all remaining bytes to the receive buffer d->buffer, but the number of remaining bytes can be larger than the buffer size. This does not lead to security problems since it is a ring buffer, but it does mess up the receive data. This can be fixed by having mux_chr_can_read return either zero or one. This fix is not very efficient, but it is quite reasonable since mux_chr_read also passes the data to the backend one byte at a time. Signed-off-by: Ruihan Li <lrh2...@pku.edu.cn> --- chardev/char-mux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chardev/char-mux.c b/chardev/char-mux.c index ee2d47b..5c6eea2 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -210,8 +210,8 @@ static int mux_chr_can_read(void *opaque) return 1; } - if (be && be->chr_can_read) { - return be->chr_can_read(be->opaque); + if (be && be->chr_can_read && be->chr_can_read(be->opaque)) { + return 1; } return 0; -- 2.45.2