diff --git a/onnxruntime/core/graph/function_utils.cc b/onnxruntime/core/graph/function_utils.cc index 9eaa3097fd..de7cec2b5d 100644 --- a/onnxruntime/core/graph/function_utils.cc +++ b/onnxruntime/core/graph/function_utils.cc @@ -123,6 +123,12 @@ static void IOTypeConstraintHelper(const ONNX_NAMESPACE::FunctionProto& onnx_fun const auto* node_op_schema = schema_registry->GetSchema(node.op_type(), domain_version, node.domain()); int variadic_arg_idx = -1; for (int i = 0; i < node.input_size(); ++i) { + if (node_op_schema && variadic_arg_idx == -1) { + // The check is applied only if we have not seen a variadic parameter so far: + ORT_ENFORCE(static_cast(i) < node_op_schema->inputs().size(), + "Too many inputs for op " + node.op_type()); + } + auto& in_name = node.input().Get(i); auto iter = input_name_idx_map.find(in_name); if (iter != input_name_idx_map.end()) { @@ -157,12 +163,12 @@ static void IOTypeConstraintHelper(const ONNX_NAMESPACE::FunctionProto& onnx_fun } } } + } - // if this is a variadic input there are no more inputs in the schema - if (node_op_schema && variadic_arg_idx == -1 && - node_op_schema->inputs().at(schema_idx).GetOption() == OpSchema::FormalParameterOption::Variadic) { - variadic_arg_idx = i; - } + // if this is a variadic input there are no more inputs in the schema + if (node_op_schema && variadic_arg_idx == -1 && + node_op_schema->inputs().at(i).GetOption() == OpSchema::FormalParameterOption::Variadic) { + variadic_arg_idx = i; } } @@ -202,12 +208,12 @@ static void IOTypeConstraintHelper(const ONNX_NAMESPACE::FunctionProto& onnx_fun } } } + } - // if this is a variadic output there are no more outputs in the schema - if (node_op_schema && variadic_arg_idx == -1 && - node_op_schema->outputs().at(schema_idx).GetOption() == OpSchema::FormalParameterOption::Variadic) { - variadic_arg_idx = i; - } + // if this is a variadic output there are no more outputs in the schema + if (node_op_schema && variadic_arg_idx == -1 && + node_op_schema->outputs().at(i).GetOption() == OpSchema::FormalParameterOption::Variadic) { + variadic_arg_idx = i; } } diff --git a/onnxruntime/test/framework/function_test.cc b/onnxruntime/test/framework/function_test.cc index 21bd301a25..2979bb8767 100644 --- a/onnxruntime/test/framework/function_test.cc +++ b/onnxruntime/test/framework/function_test.cc @@ -353,6 +353,26 @@ TEST(FunctionTest, Variadics) { ASSERT_STATUS_OK(session_object.Initialize()); } +// A variation of the variadics issue above, where the first input/output of the +// variadic list is NOT an input/output of the function. +TEST(FunctionTest, VariadicsNonInputOutput) { + const char* code = R"( + + mymodel (float[2] x) => (float[3] y) { + y = local.func (x) + } + + + func (a) => (y) { + b = Identity(a) + z = Concat (b, a, b) + y, w = Split (z) + } + )"; + + Check(code, "x", {1.0, 2.0}, "y", {1.0, 2.0, 1.0}); +} + // Test use of outer-scope names inside sub-graphs in functions that are inlined. TEST(FunctionTest, OuterScopeName) { const char* code = R"(