aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-04-05 11:30:24 +0200
committerGerd Hoffmann <kraxel@redhat.com>2013-04-16 11:52:09 +0200
commit75c439bc65c07d76f5e74c734ed5432bc6114a3b (patch)
treef7566a4e762fdfcabfc71bc25ea88f98bd2d107b
parentb010cec86b9a4a0b63162cd27e37c2d99e90ed66 (diff)
spice-qemu-char: vmc_write: Don't write more bytes then we're asked too
This one took me eons to debug, but I've finally found it now, oh well. The usage of the MIN macro in this line: last_out = MIN(len, qemu_chr_be_can_write(scd->chr)); Causes qemu_chr_be_can_write to be called *twice*, since the MIN macro evaluates its arguments twice (bad MIN macro, bad!). And the result of the call can change between the 2 calls since the guest may have consumed some data from the virtio ringbuffer between the calls! When this happens it is possible for qemu_chr_be_can_write to return less then len in the call made for the comparision, and then to return more then len in the actual call for the return-value of MIN, after which we will end up writing len data + some extra garbage, not good. This patch fixes this by only calling qemu_chr_be_can_write once. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--spice-qemu-char.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index ff95fcbe01..f10970c9db 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -35,7 +35,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
uint8_t* p = (uint8_t*)buf;
while (len > 0) {
- last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
+ int can_write = qemu_chr_be_can_write(scd->chr);
+ last_out = MIN(len, can_write);
if (last_out <= 0) {
break;
}