diff --git a/cpp/src/gandiva/precompiled/decimal_wrapper.cc b/cpp/src/gandiva/precompiled/decimal_wrapper.cc index 082d5832d14..cffb7ae9781 100644 --- a/cpp/src/gandiva/precompiled/decimal_wrapper.cc +++ b/cpp/src/gandiva/precompiled/decimal_wrapper.cc @@ -406,6 +406,8 @@ void castDECIMAL_utf8(int64_t context, const char* in, int32_t in_length, gdv_fn_dec_from_string(context, in, in_length, &precision_from_str, &scale_from_str, &dec_high_from_str, &dec_low_from_str); if (status != 0) { + *out_high = 0; + *out_low = 0; return; } diff --git a/cpp/src/gandiva/tests/decimal_test.cc b/cpp/src/gandiva/tests/decimal_test.cc index 0f2266c2cff..f8d049fd805 100644 --- a/cpp/src/gandiva/tests/decimal_test.cc +++ b/cpp/src/gandiva/tests/decimal_test.cc @@ -17,6 +17,7 @@ #include +#include #include #include "arrow/memory_pool.h" #include "arrow/status.h" @@ -1237,4 +1238,44 @@ TEST_F(TestDecimal, TestSha) { EXPECT_NE(value_at_position, response->GetScalar(i - 1).ValueOrDie()->ToString()); } } + +TEST_F(TestDecimal, TestCastDecimalVarCharInvalidInputInvalidOutput) { + auto decimal_type_10_0 = std::make_shared(10, 0); + auto decimal_type_38_30 = std::make_shared(38, 30); + auto decimal_type_38_27 = std::make_shared(38, 27); + + auto field_str = field("in_str", utf8()); + auto schema = arrow::schema({field_str}); + auto res_bool = field("res_bool", arrow::boolean()); + + // This is minimal possible expression to reproduce SIGSEGV + // equal(multiply(castDecimal(10), castDecimal(100)), castDECIMAL("foo")) + auto int_literal = TreeExprBuilder::MakeLiteral(static_cast(100)); + auto int_literal_multiply = TreeExprBuilder::MakeLiteral(static_cast(10)); + auto string_literal = TreeExprBuilder::MakeStringLiteral("foo"); + auto cast_multiply_literal = TreeExprBuilder::MakeFunction( + "castDECIMAL", {int_literal_multiply}, decimal_type_10_0); + auto cast_int_literal = + TreeExprBuilder::MakeFunction("castDECIMAL", {int_literal}, decimal_type_38_30); + auto cast_string_func = + TreeExprBuilder::MakeFunction("castDECIMAL", {string_literal}, decimal_type_38_30); + auto multiply_func = TreeExprBuilder::MakeFunction( + "multiply", {cast_multiply_literal, cast_int_literal}, decimal_type_38_27); + auto equal_func = TreeExprBuilder::MakeFunction( + "equal", {multiply_func, cast_string_func}, arrow::boolean()); + auto expr = TreeExprBuilder::MakeExpression(equal_func, res_bool); + + std::shared_ptr projector; + + ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector)); + + int num_records = 1; + auto invalid_in = MakeArrowArrayUtf8({"1.345"}, {true}); + auto in_batch = arrow::RecordBatch::Make(schema, num_records, {invalid_in}); + + arrow::ArrayVector outputs; + auto status = projector->Evaluate(*in_batch, pool_, &outputs); + ASSERT_NOT_OK(status); + ASSERT_THAT(status.message(), ::testing::HasSubstr("not a valid decimal128 number")); +} } // namespace gandiva