From 7776747f1e5b1c140e2226bae037c17d3917c0fd Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Tue, 29 Sep 2026 06:40:53 +0800 Subject: [PATCH] fix(json): validate decimal precision range before constructing DecimalType TypeFromJson's decimal branch constructed DecimalType directly after regex-parsing the numbers; the constructor throws IcebergError via CHECK_OR_DIE when precision exceeds the supported maximum of 38, so a schema string like "decimal(39, 2)" escaped the Result error contract as an uncaught exception. Check the range first and return JsonParseError, keeping malformed schema JSON inside the parse-error model. --- src/iceberg/json_serde.cc | 3 +++ src/iceberg/test/schema_json_test.cc | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/iceberg/json_serde.cc b/src/iceberg/json_serde.cc index c1c3ffb73f..3418d48370 100644 --- a/src/iceberg/json_serde.cc +++ b/src/iceberg/json_serde.cc @@ -853,6 +853,9 @@ Result> TypeFromJson(const nlohmann::json& json) { StringUtils::ParseNumber(match[1].str())); ICEBERG_ASSIGN_OR_RAISE(auto scale, StringUtils::ParseNumber(match[2].str())); + if (precision > DecimalType::kMaxPrecision) { + return JsonParseError("Invalid decimal type: {}", type_name); + } return std::make_unique(precision, scale); } return JsonParseError("Invalid decimal type: {}", type_name); diff --git a/src/iceberg/test/schema_json_test.cc b/src/iceberg/test/schema_json_test.cc index f90a0c2caf..4930d40bff 100644 --- a/src/iceberg/test/schema_json_test.cc +++ b/src/iceberg/test/schema_json_test.cc @@ -103,6 +103,13 @@ INSTANTIATE_TEST_SUITE_P( SchemaField::MakeRequired(1, "id", iceberg::int32()), SchemaField::MakeOptional(2, "name", iceberg::string())})})); +TEST(TypeJsonTest, FromJsonOutOfRangeDecimalPrecisionIsParseError) { + // Precision beyond the supported maximum must surface as a parse error, + // not an uncaught IcebergError from the DecimalType constructor. + auto result = TypeFromJson(nlohmann::json::parse("\"decimal(39, 2)\"")); + EXPECT_THAT(result, IsError(ErrorKind::kJsonParseError)); +} + TEST(TypeJsonTest, FromJsonWithSpaces) { auto fixed_json = R"("fixed[ 8 ]")"; auto fixed_result = TypeFromJson(nlohmann::json::parse(fixed_json));