From f17c01065b652ae699c716d128ec04c186001f4f Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Tue, 1 Nov 2022 12:53:24 +0100 Subject: [PATCH] Fixed value overflows break query validation. --- .../Core/src/Types/Types/Scalars/IntType.cs | 8 ++-- .../Types/Types/Scalars/IntegerTypeBase.cs | 9 +++- .../Core/src/Validation/Rules/ValueVisitor.cs | 23 ++++++++-- .../ValuesOfCorrectTypeRuleTests.cs | 13 +++++- ...uesOfCorrectTypeRuleTests.OverflowInt.snap | 44 +++++++++++++++++++ 5 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 src/HotChocolate/Core/test/Validation.Tests/__snapshots__/ValuesOfCorrectTypeRuleTests.OverflowInt.snap diff --git a/src/HotChocolate/Core/src/Types/Types/Scalars/IntType.cs b/src/HotChocolate/Core/src/Types/Types/Scalars/IntType.cs index 99848977792..2d3d0ffd8a1 100644 --- a/src/HotChocolate/Core/src/Types/Types/Scalars/IntType.cs +++ b/src/HotChocolate/Core/src/Types/Types/Scalars/IntType.cs @@ -50,9 +50,9 @@ public IntType( Description = description; } - protected override int ParseLiteral(IntValueNode valueSyntax) => - valueSyntax.ToInt32(); + protected override int ParseLiteral(IntValueNode valueSyntax) + => valueSyntax.ToInt32(); - protected override IntValueNode ParseValue(int runtimeValue) => - new(runtimeValue); + protected override IntValueNode ParseValue(int runtimeValue) + => new(runtimeValue); } diff --git a/src/HotChocolate/Core/src/Types/Types/Scalars/IntegerTypeBase.cs b/src/HotChocolate/Core/src/Types/Types/Scalars/IntegerTypeBase.cs index 359fa3b9294..64498d12616 100644 --- a/src/HotChocolate/Core/src/Types/Types/Scalars/IntegerTypeBase.cs +++ b/src/HotChocolate/Core/src/Types/Types/Scalars/IntegerTypeBase.cs @@ -27,7 +27,14 @@ protected IntegerTypeBase( protected override bool IsInstanceOfType(IntValueNode valueSyntax) { - return IsInstanceOfType(ParseLiteral(valueSyntax)); + try + { + return IsInstanceOfType(ParseLiteral(valueSyntax)); + } + catch (InvalidFormatException) + { + return false; + } } protected override bool IsInstanceOfType(TRuntimeType runtimeValue) diff --git a/src/HotChocolate/Core/src/Validation/Rules/ValueVisitor.cs b/src/HotChocolate/Core/src/Validation/Rules/ValueVisitor.cs index f7e523fd09c..4529aa6fb90 100644 --- a/src/HotChocolate/Core/src/Validation/Rules/ValueVisitor.cs +++ b/src/HotChocolate/Core/src/Validation/Rules/ValueVisitor.cs @@ -223,7 +223,7 @@ protected override ISyntaxVisitorAction Enter( inputObjectType)); } else if (value.Value.Kind is SyntaxKind.Variable && - !IsInstanceOfType(context, new NonNullType(field.Type), value.Value)) + !TryIsInstanceOfType(context, new NonNullType(field.Type), value.Value)) { context.ReportError( context.OneOfVariablesMustBeNonNull( @@ -332,7 +332,7 @@ protected override ISyntaxVisitorAction Enter( if (context.Types.TryPeek(out var currentType) && currentType is IInputType locationType) { - if (valueNode.IsNull() || IsInstanceOfType(context, locationType, valueNode)) + if (valueNode.IsNull() || TryIsInstanceOfType(context, locationType, valueNode)) { return Skip; } @@ -348,7 +348,7 @@ protected override ISyntaxVisitorAction Enter( return Skip; } - private bool TryCreateValueError( + private static bool TryCreateValueError( IDocumentValidatorContext context, IInputType locationType, IValueNode valueNode, @@ -390,6 +390,23 @@ private bool TryPeekLastDefiningSyntaxNode( return false; } + private bool TryIsInstanceOfType( + IDocumentValidatorContext context, + IInputType inputType, + IValueNode value) + { + try + { + return IsInstanceOfType(context, inputType, value); + } + // in the case a scalar IsInstanceOfType check is not done well an throws we will + // catch this here and make sure that the validation fails correctly. + catch + { + return false; + } + } + private bool IsInstanceOfType( IDocumentValidatorContext context, IInputType inputType, diff --git a/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs b/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs index a86c062ea22..1d407819102 100644 --- a/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs +++ b/src/HotChocolate/Core/test/Validation.Tests/ValuesOfCorrectTypeRuleTests.cs @@ -211,6 +211,17 @@ public void GoodIntNegativeValue() "); } + [Fact] + public void OverflowInt() + { + ExpectErrors($@" + {{ + arguments {{ + intArgField(intArg: {long.MaxValue}) + }} + }}"); + } + [Fact] public void GoodNullToBooleanNullableValue() { @@ -1173,4 +1184,4 @@ query InvalidItem($a: [String] = [""one"", 2]) { } "); } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/ValuesOfCorrectTypeRuleTests.OverflowInt.snap b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/ValuesOfCorrectTypeRuleTests.OverflowInt.snap new file mode 100644 index 00000000000..b166e703ce2 --- /dev/null +++ b/src/HotChocolate/Core/test/Validation.Tests/__snapshots__/ValuesOfCorrectTypeRuleTests.OverflowInt.snap @@ -0,0 +1,44 @@ +[ + { + "Message": "The specified argument value does not match the argument type.", + "Code": null, + "Path": { + "Name": "intArgField", + "Parent": { + "Name": "arguments", + "Parent": { + "Parent": null, + "Depth": -1, + "IsRoot": true + }, + "Depth": 0, + "IsRoot": false + }, + "Depth": 1, + "IsRoot": false + }, + "Locations": [ + { + "Line": 4, + "Column": 37 + } + ], + "Extensions": { + "argument": "intArg", + "argumentValue": "9223372036854775807", + "locationType": "Int", + "specifiedBy": "http://spec.graphql.org/October2021/#sec-Values-of-Correct-Type" + }, + "Exception": null, + "SyntaxNode": { + "Kind": "IntValue", + "Location": { + "Start": 77, + "End": 97, + "Line": 4, + "Column": 37 + }, + "Value": "9223372036854775807" + } + } +]