From 6a9dc75cc23ccb8f918d3ba92873ff160cff4941 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 9 Sep 2020 12:22:44 +0200 Subject: [PATCH] nir: Fix undefined behavior due to signed integer multiplication overflows Notably this happened when applying constant folding on the intermediate computations generated from nir_lower_idiv. Reviewed-by: Rhys Perry Part-of: --- src/compiler/nir/nir_opcodes.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py index 27b09fa..8226be0 100644 --- a/src/compiler/nir/nir_opcodes.py +++ b/src/compiler/nir/nir_opcodes.py @@ -625,7 +625,10 @@ if (nir_is_rounding_mode_rtz(execution_mode, bit_size)) { } """) # low 32-bits of signed/unsigned integer multiply -binop("imul", tint, _2src_commutative + associative, "src0 * src1") +binop("imul", tint, _2src_commutative + associative, """ + /* Use 64-bit multiplies to prevent overflow of signed arithmetic */ + dst = (uint64_t)src0 * (uint64_t)src1; +""") # Generate 64 bit result from 2 32 bits quantity binop_convert("imul_2x32_64", tint64, tint32, _2src_commutative, @@ -656,7 +659,9 @@ if (bit_size == 64) { ubm_mul_u32arr(prod_u32, src0_u32, src1_u32); dst = (uint64_t)prod_u32[2] | ((uint64_t)prod_u32[3] << 32); } else { - dst = ((int64_t)src0 * (int64_t)src1) >> bit_size; + /* First, sign-extend to 64-bit, then convert to unsigned to prevent + * potential overflow of signed multiply */ + dst = ((uint64_t)(int64_t)src0 * (uint64_t)(int64_t)src1) >> bit_size; } """) -- 2.7.4