diff --git a/c++/src/TypeImpl.cc b/c++/src/TypeImpl.cc index cbc7b82796..70a6e55e4a 100644 --- a/c++/src/TypeImpl.cc +++ b/c++/src/TypeImpl.cc @@ -420,7 +420,20 @@ namespace orc { } std::string printProtobufMessage(const google::protobuf::Message& message); - std::unique_ptr convertType(const proto::Type& type, const proto::Footer& footer) { + // Bound the recursion over the (file-controlled) type tree. The footer describes the schema as a + // tree of LIST/MAP/UNION/STRUCT types nested arbitrarily deep; a crafted deeply nested schema + // would overflow the native stack here, and later in assignIds()/buildTypeNameIdMap() which walk + // the same tree. The limit is far above any legitimate schema. + static const uint64_t MAX_TYPE_NESTING_DEPTH = 2000; + + std::unique_ptr convertType(const proto::Type& type, const proto::Footer& footer, + uint64_t depth) { + if (depth > MAX_TYPE_NESTING_DEPTH) { + std::stringstream msg; + msg << "Footer is corrupt: type nesting depth exceeds the limit of " << MAX_TYPE_NESTING_DEPTH; + throw ParseError(msg.str()); + } + std::unique_ptr ret; switch (static_cast(type.kind())) { case proto::Type_Kind_BOOLEAN: @@ -458,7 +471,8 @@ namespace orc { if (type.kind() == proto::Type_Kind_UNION && type.subtypes_size() == 0) throw ParseError("Illegal UNION type that doesn't contain any subtypes"); for (int i = 0; i < type.subtypes_size(); ++i) { - ret->addUnionChild(convertType(footer.types(static_cast(type.subtypes(i))), footer)); + ret->addUnionChild( + convertType(footer.types(static_cast(type.subtypes(i))), footer, depth + 1)); } break; } @@ -470,7 +484,7 @@ namespace orc { for (int i = 0; i < type.subtypes_size(); ++i) { ret->addStructField( type.field_names(i), - convertType(footer.types(static_cast(type.subtypes(i))), footer)); + convertType(footer.types(static_cast(type.subtypes(i))), footer, depth + 1)); } break; } diff --git a/c++/src/TypeImpl.hh b/c++/src/TypeImpl.hh index 647d5a5d2c..0a55124362 100644 --- a/c++/src/TypeImpl.hh +++ b/c++/src/TypeImpl.hh @@ -187,7 +187,8 @@ namespace orc { size_t start, size_t end); }; - std::unique_ptr convertType(const proto::Type& type, const proto::Footer& footer); + std::unique_ptr convertType(const proto::Type& type, const proto::Footer& footer, + uint64_t depth = 0); /** * Build a clone of the file type, projecting columns from the selected