From e0c026cdfc42fe6029c2389b55bb1c1300549f73 Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Sun, 27 Nov 2022 18:40:44 +0000 Subject: [PATCH] fix Interval multiplication when result exceeds int64_max (#14230) * fix Interval multiplication when result exceeds int64_max * added unit-test with corner cases --- src/core/src/interval.cpp | 2 +- src/core/tests/dimension.cpp | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/core/src/interval.cpp b/src/core/src/interval.cpp index 7a354ec97c1..b487681587c 100644 --- a/src/core/src/interval.cpp +++ b/src/core/src/interval.cpp @@ -14,7 +14,7 @@ Interval::value_type clip(Interval::value_type value) { Interval::value_type clip_times(Interval::value_type a, Interval::value_type b) { if (a == 0 || b == 0) { return 0; - } else if (a == Interval::s_max || b == Interval::s_max) { + } else if (a == Interval::s_max || b == Interval::s_max || a > Interval::s_max / b) { return Interval::s_max; } else { return a * b; diff --git a/src/core/tests/dimension.cpp b/src/core/tests/dimension.cpp index 6d5a69d557b..95300f441a2 100644 --- a/src/core/tests/dimension.cpp +++ b/src/core/tests/dimension.cpp @@ -54,6 +54,55 @@ TEST(dimension, broadcast_merge_static_0_12_and_1_15) { EXPECT_EQ(result, Dimension(0, 15)); } +TEST(dimension, dimension_mul_operator_ordinary_intervals) { + Dimension interval_1(0, 10); + Dimension interval_2(2, 100); + Dimension ref_value(0, 1000); + EXPECT_EQ(ref_value, interval_1 * interval_2); +} + +TEST(dimension, dimension_mul_operator_1) { + Dimension fully_dynamic_dim(-1); + Dimension two(2); + Dimension ref_value(-1); + EXPECT_EQ(ref_value, fully_dynamic_dim * two); +} + +TEST(dimension, dimension_mul_operator_2) { + Dimension large_interval(2, 9223372036854775806); + Dimension two(2); + Dimension ref_value(4, 9223372036854775807); + EXPECT_EQ(ref_value, large_interval * two); +} + +TEST(dimension, dimension_mul_operator_3) { + // no overflow + Dimension large_interval(2, 4611686018427387903); + Dimension two(2); + Dimension ref_value(4, 9223372036854775806); + EXPECT_EQ(ref_value, large_interval * two); +} + +TEST(dimension, dimension_mul_operator_4) { + // overflow happens and clip_times keeps result within in64 limits + // 4611686018427387904 * 2 = 9223372036854775808 = int64_max - 1 + // 9223372036854775808 does not fin into int64, is clipped into int64_max + Dimension large_interval(2, 4611686018427387904); + Dimension two(2); + Dimension ref_value(4, 9223372036854775807); + EXPECT_EQ(ref_value, large_interval * two); +} + +TEST(dimension, dimension_mul_operator_5) { + // overflow happens and clip_times keeps result within in64 limits + // 3074457345618258604 * 3 = 9223372036854775812 + // 9223372036854775812 does not fit into int64, is clipped into int64_max + Dimension large_interval(2, 3074457345618258604); + Dimension three(3); + Dimension ref_value(6, 9223372036854775807); + EXPECT_EQ(ref_value, large_interval * three); +} + TEST(dimension, division_of_static_dims_twenty_three_div_three_eq_seven) { Dimension twenty_three(23); Dimension::value_type three(3);