From 6b033c2619595ede2cb193030ad2ec74b597d3d8 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 6 Sep 2018 20:47:09 +0300 Subject: [PATCH] Prevent infinite loop on invalid introspection (#1509) --- .../__tests__/buildClientSchema-test.js | 37 +++++++++++++++++++ src/utilities/buildClientSchema.js | 4 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/utilities/__tests__/buildClientSchema-test.js b/src/utilities/__tests__/buildClientSchema-test.js index 4d1961af06..a6950630e4 100644 --- a/src/utilities/__tests__/buildClientSchema-test.js +++ b/src/utilities/__tests__/buildClientSchema-test.js @@ -844,4 +844,41 @@ describe('Type System: build schema from introspection', () => { buildClientSchema(introspection); }); }); + + describe('prevents infinite recursion on invalid introspection', () => { + it('recursive interfaces', () => { + const introspection = { + __schema: { + types: [ + { + name: 'Foo', + kind: 'OBJECT', + fields: [], + interfaces: [{ name: 'Foo' }], + }, + ], + }, + }; + expect(() => buildClientSchema(introspection)).to.throw( + 'Expected Foo to be a GraphQL Interface type.', + ); + }); + + it('recursive union', () => { + const introspection = { + __schema: { + types: [ + { + name: 'Foo', + kind: 'UNION', + possibleTypes: [{ name: 'Foo' }], + }, + ], + }, + }; + expect(() => buildClientSchema(introspection)).to.throw( + 'Expected Foo to be a GraphQL Object type.', + ); + }); + }); }); diff --git a/src/utilities/buildClientSchema.js b/src/utilities/buildClientSchema.js index eef0c24596..531036dca3 100644 --- a/src/utilities/buildClientSchema.js +++ b/src/utilities/buildClientSchema.js @@ -221,7 +221,7 @@ export function buildClientSchema( return new GraphQLObjectType({ name: objectIntrospection.name, description: objectIntrospection.description, - interfaces: objectIntrospection.interfaces.map(getInterfaceType), + interfaces: () => objectIntrospection.interfaces.map(getInterfaceType), fields: () => buildFieldDefMap(objectIntrospection), }); } @@ -248,7 +248,7 @@ export function buildClientSchema( return new GraphQLUnionType({ name: unionIntrospection.name, description: unionIntrospection.description, - types: unionIntrospection.possibleTypes.map(getObjectType), + types: () => unionIntrospection.possibleTypes.map(getObjectType), }); }