0067bd1
From ad0343a9c903b79c6dd3ecdafb05a704c14514b9 Mon Sep 17 00:00:00 2001
0067bd1
From: Hans de Goede <hdegoede@redhat.com>
0067bd1
Date: Fri, 5 Apr 2013 11:30:24 +0200
0067bd1
Subject: [PATCH] spice-qemu-char: vmc_write: Don't write more bytes then we're
0067bd1
 asked too
0067bd1
0067bd1
This one took me eons to debug, but I've finally found it now, oh well.
0067bd1
0067bd1
The usage of the MIN macro in this line:
0067bd1
    last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
0067bd1
0067bd1
Causes qemu_chr_be_can_write to be called *twice*, since the MIN macro
0067bd1
evaluates its arguments twice (bad MIN macro, bad!). And the result of
0067bd1
the call can change between the 2 calls since the guest may have consumed
0067bd1
some data from the virtio ringbuffer between the calls!
0067bd1
0067bd1
When this happens it is possible for qemu_chr_be_can_write to return less
0067bd1
then len in the call made for the comparision, and then to return more then
0067bd1
len in the actual call for the return-value of MIN, after which we will end
0067bd1
up writing len data + some extra garbage, not good.
0067bd1
0067bd1
This patch fixes this by only calling qemu_chr_be_can_write once.
0067bd1
0067bd1
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
0067bd1
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
0067bd1
(cherry picked from commit 75c439bc65c07d76f5e74c734ed5432bc6114a3b)
0067bd1
---
0067bd1
 spice-qemu-char.c | 3 ++-
0067bd1
 1 file changed, 2 insertions(+), 1 deletion(-)
0067bd1
0067bd1
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
0067bd1
index 5065240..82f3f77 100644
0067bd1
--- a/spice-qemu-char.c
0067bd1
+++ b/spice-qemu-char.c
0067bd1
@@ -41,7 +41,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
0067bd1
     uint8_t* p = (uint8_t*)buf;
0067bd1
 
0067bd1
     while (len > 0) {
0067bd1
-        last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
0067bd1
+        int can_write = qemu_chr_be_can_write(scd->chr);
0067bd1
+        last_out = MIN(len, can_write);
0067bd1
         if (last_out <= 0) {
0067bd1
             break;
0067bd1
         }