Skip to content

Commit fb8d576

Browse files
committed
Prevent infinite loop on invalid introspection
Replicates graphql/graphql-js@6b033c2
1 parent 0a477fe commit fb8d576

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ a query language for APIs created by Facebook.
1313

1414
The current version 1.0.0 of GraphQL-core-next is up-to-date with GraphQL.js
1515
version 14.0.1. All parts of the API are covered by an extensive test suite of
16-
currently 1604 unit tests.
16+
currently 1606 unit tests.
1717

1818

1919
## Documentation

graphql/utilities/build_client_schema.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import cast, Callable, Dict, Sequence
1+
from typing import cast, Callable, Dict, List, Sequence
22

33
from ..error import INVALID
44
from ..language import DirectiveLocation, parse_value
@@ -126,8 +126,9 @@ def build_object_def(object_introspection: Dict) -> GraphQLObjectType:
126126
return GraphQLObjectType(
127127
name=object_introspection['name'],
128128
description=object_introspection.get('description'),
129-
interfaces=[
130-
get_interface_type(interface) for interface in interfaces],
129+
interfaces=lambda: [
130+
get_interface_type(interface)
131+
for interface in cast(List[Dict], interfaces)],
131132
fields=lambda: build_field_def_map(object_introspection))
132133

133134
def build_interface_def(
@@ -146,7 +147,8 @@ def build_union_def(union_introspection: Dict) -> GraphQLUnionType:
146147
return GraphQLUnionType(
147148
name=union_introspection['name'],
148149
description=union_introspection.get('description'),
149-
types=[get_object_type(type_) for type_ in possible_types])
150+
types=lambda: [get_object_type(type_)
151+
for type_ in cast(List[Dict], possible_types)])
150152

151153
def build_enum_def(enum_introspection: Dict) -> GraphQLEnumType:
152154
if enum_introspection.get('enumValues') is None:

tests/utilities/test_build_client_schema.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,3 +448,38 @@ def succeeds_on_deep_types_less_or_equal_7_levels():
448448

449449
introspection = introspection_from_schema(schema)
450450
build_client_schema(introspection)
451+
452+
def describe_prevents_infinite_recursion_on_invalid_introspection():
453+
454+
def recursive_interfaces():
455+
introspection = {
456+
'__schema': {
457+
'types': [{
458+
'name': 'Foo',
459+
'kind': 'OBJECT',
460+
'fields': [],
461+
'interfaces': [{'name': 'Foo'}],
462+
}],
463+
},
464+
}
465+
with raises(TypeError) as exc_info:
466+
build_client_schema(introspection)
467+
assert str(exc_info.value) == (
468+
'Foo interfaces cannot be resolved: '
469+
'Expected Foo to be a GraphQL Interface type.')
470+
471+
def recursive_union():
472+
introspection = {
473+
'__schema': {
474+
'types': [{
475+
'name': 'Foo',
476+
'kind': 'UNION',
477+
'possibleTypes': [{'name': 'Foo'}],
478+
}],
479+
},
480+
}
481+
with raises(TypeError) as exc_info:
482+
build_client_schema(introspection)
483+
assert str(exc_info.value) == (
484+
'Foo types cannot be resolved: '
485+
'Expected Foo to be a GraphQL Object type.')

0 commit comments

Comments
 (0)