diff --git a/src/Functions/array/mapOp.cpp b/src/Functions/array/mapOp.cpp index 62662099961..ec33f48f42b 100644 --- a/src/Functions/array/mapOp.cpp +++ b/src/Functions/array/mapOp.cpp @@ -120,6 +120,12 @@ private: return res; } + template + static inline auto NO_SANITIZE_UNDEFINED negate(T x) + { + return -x; + } + template ColumnPtr execute2(size_t row_count, TupleMaps & args, const DataTypeTuple & res_type) const { @@ -159,14 +165,14 @@ private: if constexpr (is_str_key) { // have to use Field structs to get strings - key = arg.key_column.operator[](offset + j).get(); + key = arg.key_column[offset + j].get(); } else { key = assert_cast &>(arg.key_column).getData()[offset + j]; } - auto value = arg.val_column.operator[](offset + j).get(); + ValType value = arg.val_column[offset + j].get(); if constexpr (op_type == OpTypes::ADD) { @@ -177,7 +183,7 @@ private: else { static_assert(op_type == OpTypes::SUBTRACT); - const auto [it, inserted] = summing_map.insert({key, first ? value : -value}); + const auto [it, inserted] = summing_map.insert({key, first ? value : negate(value)}); if (!inserted) it->second -= value; } diff --git a/tests/queries/0_stateless/01781_map_op_ubsan.reference b/tests/queries/0_stateless/01781_map_op_ubsan.reference new file mode 100644 index 00000000000..030c8bb5ab4 --- /dev/null +++ b/tests/queries/0_stateless/01781_map_op_ubsan.reference @@ -0,0 +1 @@ +\N (([0,10,255],[-9223372036854775808,1025,0]),[255,NULL]) \N ([0,255],3,[-2]) [NULL] diff --git a/tests/queries/0_stateless/01781_map_op_ubsan.sql b/tests/queries/0_stateless/01781_map_op_ubsan.sql new file mode 100644 index 00000000000..adbb5d5a8d7 --- /dev/null +++ b/tests/queries/0_stateless/01781_map_op_ubsan.sql @@ -0,0 +1 @@ +SELECT toInt32([toUInt8(NULL)], NULL), (mapSubtract(([toUInt8(256), 10], [toInt32(-9223372036854775808), 1025]), ([toUInt8(65535), 0], [toInt16(0.), -9223372036854775808])), [toUInt8(-1), toInt32(([toUInt8(9223372036854775807), -1], [toInt32(255), 65536]), NULL)]), toUInt8(([2, 9223372036854775807], [toFloat32('0.0000065536'), 2]), 9223372036854775807, NULL), ([toUInt8(1024), 255], toUInt8(3), [toInt16(-2)]), [NULL];