Skip to content

Commit 6076716

Browse files
committed
Fail with an error naming the cycle when unions contain themselves
getLeafUnionObjects expanded nested unions recursively without tracking which ones it was already expanding, so a union that lists itself, directly or through another union, overflowed the stack. It now keeps the path of unions it is expanding and throws a SchemaError that names the cycle and points at the member that closes it.
1 parent 6a6a869 commit 6076716

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

‎src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,11 @@ class SchemaParser internal constructor(
345345
return builder.build()
346346
}
347347

348-
private fun getLeafUnionObjects(definition: UnionTypeDefinition, types: List<GraphQLObjectType>): List<GraphQLObjectType> {
348+
private fun getLeafUnionObjects(
349+
definition: UnionTypeDefinition,
350+
types: List<GraphQLObjectType>,
351+
path: List<UnionTypeDefinition> = listOf(definition),
352+
): List<GraphQLObjectType> {
349353
val name = definition.name
350354
val leafObjects = mutableListOf<GraphQLObjectType>()
351355

@@ -356,7 +360,11 @@ class SchemaParser internal constructor(
356360
val nestedUnion: UnionTypeDefinition? = unionDefinitions.find { otherDefinition -> typeName == otherDefinition.name }
357361

358362
if (nestedUnion != null) {
359-
leafObjects.addAll(getLeafUnionObjects(nestedUnion, types))
363+
if (nestedUnion in path) {
364+
val cycle = (path.dropWhile { union -> union != nestedUnion } + nestedUnion).joinToString(" -> ") { union -> union.name }
365+
throw SchemaError("Union '$typeName' contains itself through $cycle${it.sourceLocation.describe()}.")
366+
}
367+
leafObjects.addAll(getLeafUnionObjects(nestedUnion, types, path + nestedUnion))
360368
} else {
361369
leafObjects.add(types.find { type -> type.name == typeName }
362370
?: throw SchemaError("Expected object type '$typeName' for union type '$name', but found none!"))

0 commit comments

Comments
 (0)