Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,10 @@
* Fixed validation of an inline fragment without a type condition (`... { … }`), which used to fail with an exception instead of applying to the parent type
* Fixed the GraphQL client provider building `Operation<...>` again for every file that uses the same operation, which added another operation type of the same name to `Operations` each time
* Removed the internal `Observable.withCompletionMarker`
* **Breaking Change** Validation now rejects a document, before building anything else for it, when validating it would inline more than `DocumentLimitsDefaults.MaxRecursiveSelections` (25 000) selections or nest deeper than `DocumentLimitsDefaults.MaxNestingDepth` (128) levels. Selections are fields, inline fragments and fragment spreads, counted over all the operations and fragment definitions of the document with their fragment spreads inlined, and each inline fragment and fragment spread adds a nesting level. Validation also stops after `DocumentLimitsDefaults.MaxValidationErrors` (100) errors and then adds a final "Too many validation errors, error limit reached. Validation aborted." error, as graphql-js does
* **Breaking Change** Validation no longer inlines the spreads of fragments that form a cycle, so it reports the cycle but not the other errors inside those fragments' spreads. The fragment cycle rule now reports each fragment of a cycle once, including fragments whose type condition is not in the schema, and no longer reports fragments that only spread a cycle
* Fixed a stack overflow that crashed the whole server when a document contained a subscription operation spreading a fragment that spreads itself, even when that operation was not the one executed and the schema had no subscription type
* Fixed validation time growing exponentially with fragments that spread other fragments several times, and factorially with fragments that spread each other in a cycle: a document of 20 such fragments and 821 characters took 31 seconds to validate
* Fixed validation error accumulation, which was quadratic in the number of errors
* Fixed the subscription single root field rule ignoring the fields selected before a fragment spread and counting a fragment spread twice when it is spread twice
* Added `AstError.Create`, which creates a validation error
32 changes: 32 additions & 0 deletions src/FSharp.Data.GraphQL.Shared/DocumentLimits.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace FSharp.Data.GraphQL

/// Default limits on the work that an untrusted document can cause while it is validated.
[<RequireQualifiedAccess>]
module DocumentLimitsDefaults =

/// <summary>
/// The maximum nesting depth of a document once its fragment spreads are inlined.
/// <para>
/// Every selection set of a field, every inline fragment and every fragment spread adds one level.
/// </para>
/// </summary>
[<Literal>]
let MaxNestingDepth = 128

/// <summary>
/// The maximum number of selections that the validation of a document may inline.
/// <para>
/// Fields, inline fragments and fragment spreads are counted after fragment spreads are inlined, over all the
/// operations and fragment definitions of the document.
/// </para>
/// <para>
/// Validation and planning take time in proportion to this number, so a higher limit lets a small document
/// keep a server busy for longer.
/// </para>
/// </summary>
[<Literal>]
let MaxRecursiveSelections = 25_000

/// The maximum number of errors that the validation of a document reports before it stops.
[<Literal>]
let MaxValidationErrors = 100
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Compile Include="Helpers\MemoryCache.fs" />
<Compile Include="Errors.fs" />
<Compile Include="Exception.fs" />
<Compile Include="DocumentLimits.fs" />
<Compile Include="ValidationTypes.fs" />
<Compile Include="AsyncVal.fs" />
<Compile Include="Ast.fs" />
Expand Down
Loading
Loading