The multiplication of (value - min_in) * range_out can overflow
int64_t when both operands are large. Use muldiv64() to compute
the scaled result without overflow. Note that muldiv64() takes
uint32_t for its multiplier and divisor, which is sufficient
here since all function parameters are int (32-bit on all
supported host architectures).

Reported-by: Pavee Hui <[email protected]>
Fixes: 43579403a3d6 ("input: mouse: add helpers functions to core")
Signed-off-by: Marc-André Lureau <[email protected]>
---
 ui/input.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/ui/input.c b/ui/input.c
index b82622c8645d..f40a9883701e 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -5,6 +5,7 @@
 #include "trace.h"
 #include "ui/input.h"
 #include "ui/console.h"
+#include "qemu/host-utils.h"
 #include "system/replay.h"
 #include "system/runstate.h"
 
@@ -492,11 +493,16 @@ int qemu_input_scale_axis(int value,
 {
     int64_t range_in = (int64_t)max_in - min_in;
     int64_t range_out = (int64_t)max_out - min_out;
+    int64_t diff = (int64_t)value - min_in;
+    bool neg;
+    int64_t scaled;
 
     if (range_in < 1) {
         return min_out + range_out / 2;
     }
-    return ((int64_t)value - min_in) * range_out / range_in + min_out;
+    neg = (diff < 0) != (range_out < 0);
+    scaled = muldiv64(llabs(diff), llabs(range_out), llabs(range_in));
+    return (neg ? -scaled : scaled) + min_out;
 }
 
 void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)

-- 
2.56.0.rc0.29.g47ce80527c56


Reply via email to