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
