From 56e9dadce4d268e767a72ec44efd0f830a7ffd65 Mon Sep 17 00:00:00 2001 From: Vlv <190944823+xiaobai0529@users.noreply.github.com> Date: Wed, 21 Oct 2026 19:25:17 +0800 Subject: [PATCH] fix(substrait): validate decimal precision before constructing type --- cpp/src/arrow/engine/substrait/serde_test.cc | 17 +++++++++++++++++ cpp/src/arrow/engine/substrait/type_internal.cc | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/engine/substrait/serde_test.cc b/cpp/src/arrow/engine/substrait/serde_test.cc index 311876379830..04367d4c20f5 100644 --- a/cpp/src/arrow/engine/substrait/serde_test.cc +++ b/cpp/src/arrow/engine/substrait/serde_test.cc @@ -71,6 +71,7 @@ #include "arrow/type.h" #include "arrow/type_fwd.h" #include "arrow/util/async_generator_fwd.h" +#include "arrow/util/base64.h" #include "arrow/util/checked_cast.h" #include "arrow/util/config.h" #include "arrow/util/decimal.h" @@ -1581,6 +1582,22 @@ TEST(Substrait, InvalidEmptyExtensionDeclaration) { ASSERT_RAISES(Invalid, DeserializePlans(*buf, [] { return kNullConsumer; })); } +TEST(Substrait, InvalidDecimalPrecisionReturnsStatus) { + // GH-50230: a decimal precision outside [1, 38] must produce an error rather + // than aborting the process in the Decimal128Type constructor. + constexpr std::string_view kPocBase64 = + "GswBCskBCsYBEr4BCgJjMAoCYzEKAmMyCgJjMwoCYzQKAmM1CgJjNgoCYzcKAmM4CgJjOQoDYzEw" + "CgNjMTEKA2MxMgoDYzEzCgNjMTQKA2MxNQoDYzE2CgNjMTcSbAoCCgAKAhIACgIaAAoCKgAKAjoA" + "CgJSAAoCWgAKAmIACgJqAAoCcgAKA4IBAAoDigEACgfCAQQIAhAqCgWqAQIIBAoFsgECCAgKB9oB" + "BAoCOgAKC+IBCAoCYgASAjoACgvKAQgKAioACgJiADoDCgF0MgsQLCoHbzItc2VlZA=="; + ASSERT_OK_AND_ASSIGN(auto poc, util::base64_decode(kPocBase64)); + ASSERT_EQ(poc.size(), 220); + + EXPECT_THAT(DeserializePlan(*Buffer::FromString(std::move(poc)), + /*registry=*/nullptr, /*ext_set_out=*/nullptr), + Raises(StatusCode::Invalid, HasSubstr("Decimal precision out of range"))); +} + TEST(Substrait, JoinPlanBasic) { std::string substrait_json = R"({ "version": { "major_number": 9999, "minor_number": 9999, "patch_number": 9999 }, diff --git a/cpp/src/arrow/engine/substrait/type_internal.cc b/cpp/src/arrow/engine/substrait/type_internal.cc index 3e8c0dda765b..3abc1ac18bee 100644 --- a/cpp/src/arrow/engine/substrait/type_internal.cc +++ b/cpp/src/arrow/engine/substrait/type_internal.cc @@ -171,7 +171,9 @@ Result, bool>> FromProto( case substrait::Type::kDecimal: { const auto& decimal = type.decimal(); - return FromProtoImpl(decimal, decimal.precision(), decimal.scale()); + ARROW_ASSIGN_OR_RAISE(auto decimal_type, + Decimal128Type::Make(decimal.precision(), decimal.scale())); + return std::make_pair(std::move(decimal_type), IsNullable(decimal)); } case substrait::Type::kStruct: {