From c28c77e4589e65336faa8ac8aa48a17fe037598b Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 21:59:50 -0800 Subject: [PATCH 01/17] Fix panic on malformed queries with recursive fragments. This is a potential denial-of-service attack vector. Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps. --- juniper/CHANGELOG.md | 2 +- .../rules/overlapping_fields_can_be_merged.rs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md index 4b08aa5e..68ebe542 100644 --- a/juniper/CHANGELOG.md +++ b/juniper/CHANGELOG.md @@ -1,6 +1,6 @@ # master -- No changes yet +- Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps. # [[0.15.7] 2021-07-08](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.7) diff --git a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs index ce42cbd8..f26dcfdf 100644 --- a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -172,6 +172,13 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { ); for frag_name2 in &fragment_names[i + 1..] { + // Prevent infinite fragment recursion. This case is + // caught by fragment validators, but because the validation is + // done in parallel we can't rely on fragments being + // non-recursive here. + if frag_name1 == frag_name2 { + continue; + } self.collect_conflicts_between_fragments( &mut conflicts, frag_name1, @@ -195,6 +202,10 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { ) where S: ScalarValue, { + // Prevent infinite fragment recursion. This case is + // caught by fragment validators, but because the validation is + // done in parallel we can't rely on fragments being + // non-recursive here. if fragment_name1 == fragment_name2 { return; } @@ -282,6 +293,13 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { self.collect_conflicts_between(conflicts, mutually_exclusive, field_map, &field_map2, ctx); for fragment_name2 in fragment_names2 { + // Prevent infinite fragment recursion. This case is + // caught by fragment validators, but because the validation is + // done in parallel we can't rely on fragments being + // non-recursive here. + if fragment_name == fragment_name2 { + return; + } self.collect_conflicts_between_fields_and_fragment( conflicts, field_map, @@ -2261,6 +2279,26 @@ mod tests { ); } + #[test] + fn handles_recursive_fragments() { + expect_passes_rule_with_schema::< + _, + EmptyMutation<()>, + EmptySubscription<()>, + _, + _, + DefaultScalarValue, + >( + QueryRoot, + EmptyMutation::new(), + EmptySubscription::new(), + factory, + r#" + fragment f on Query { ...f } + "#, + ); + } + #[test] fn error_message_contains_hint_for_alias_conflict() { assert_eq!( From 399a79056ac523bf19192b7a62920dbe28c83d52 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 22:46:32 -0800 Subject: [PATCH 02/17] Update key for newer cargo-release --- _build/release.toml | 2 +- juniper/release.toml | 2 +- juniper_codegen/release.toml | 2 +- juniper_graphql_ws/release.toml | 2 +- juniper_subscriptions/release.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_build/release.toml b/_build/release.toml index bbe12430..72d403b5 100644 --- a/_build/release.toml +++ b/_build/release.toml @@ -1,6 +1,6 @@ no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" -pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" +post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" pre-release-replacements = [ {file="CHANGELOG.md", min=0, search="# master", replace="# master\n\n- Compatibility with the latest `juniper`.\n\n# [[{{version}}] {{date}}](https://github.com/graphql-rust/juniper/releases/tag/{{crate_name}}-{{version}})"}, diff --git a/juniper/release.toml b/juniper/release.toml index 7831d4e2..54388c07 100644 --- a/juniper/release.toml +++ b/juniper/release.toml @@ -1,6 +1,6 @@ no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" -pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" +post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" pre-release-replacements = [ # Juniper's changelog diff --git a/juniper_codegen/release.toml b/juniper_codegen/release.toml index 51b3405b..ec5368a9 100644 --- a/juniper_codegen/release.toml +++ b/juniper_codegen/release.toml @@ -1,6 +1,6 @@ no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" -pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" +post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" pre-release-replacements = [ {file="../juniper/Cargo.toml", min=0, search="juniper_codegen = \\{ version = \"[^\"]+\"", replace="juniper_codegen = { version = \"{{version}}\""}, diff --git a/juniper_graphql_ws/release.toml b/juniper_graphql_ws/release.toml index 786a2308..90382749 100644 --- a/juniper_graphql_ws/release.toml +++ b/juniper_graphql_ws/release.toml @@ -1,6 +1,6 @@ no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" -pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" +post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" pre-release-replacements = [ {file="src/lib.rs", min=0, search="docs.rs/juniper_graphql_ws/[a-z0-9\\.-]+", replace="docs.rs/juniper_graphql_ws/{{version}}"}, diff --git a/juniper_subscriptions/release.toml b/juniper_subscriptions/release.toml index 237641db..f84ce2b0 100644 --- a/juniper_subscriptions/release.toml +++ b/juniper_subscriptions/release.toml @@ -1,6 +1,6 @@ no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" -pro-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" +post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" pre-release-replacements = [ {file="../juniper_graphql_ws/Cargo.toml", min=0, search="juniper_subscriptions = \\{ version = \"[^\"]+\"", replace="juniper_subscriptions = { version = \"{{version}}\""}, From 4b0aabe9f6b4a7ddd9fccc9d3eabb5b1829bea41 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:11:17 -0800 Subject: [PATCH 03/17] More breaking changes with cargo-release 0.19.0 --- Makefile.toml | 6 +++--- _build/release.toml | 1 - juniper/Makefile.toml | 6 +++--- juniper/release.toml | 1 - juniper_codegen/Makefile.toml | 6 +++--- juniper_codegen/release.toml | 1 - juniper_graphql_ws/Makefile.toml | 7 ++++--- juniper_graphql_ws/release.toml | 1 - juniper_subscriptions/Makefile.toml | 6 +++--- juniper_subscriptions/release.toml | 1 - 10 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index 812ce9a6..a23a63ba 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -12,7 +12,7 @@ CARGO_MAKE_WORKSPACE_SKIP_MEMBERS = "integration_tests/*;examples/*;juniper_benc [tasks.release] condition = { env_set = [ "RELEASE_LEVEL" ] } command = "cargo-release" -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--execute", "${RELEASE_LEVEL}"] # Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-dry-run` to do a dry run. @@ -23,7 +23,7 @@ args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/releas condition = { env_set = [ "RELEASE_LEVEL" ] } description = "Run `cargo-release --dry-run` for every crate" command = "cargo-release" -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--dry-run", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"] # Run `RELEASE_LEVEL=(patch|major|minor) cargo make release-local-test` to actually make changes locally but @@ -35,4 +35,4 @@ args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/releas condition = { env_set = [ "RELEASE_LEVEL" ] } description = "Run `cargo-release` for every crate, but only make changes locally" command = "cargo-release" -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/../_build/release.toml", "--no-confirm", "${RELEASE_LEVEL}"] diff --git a/_build/release.toml b/_build/release.toml index 72d403b5..b0acba60 100644 --- a/_build/release.toml +++ b/_build/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" diff --git a/juniper/Makefile.toml b/juniper/Makefile.toml index 6f6e065e..6736f477 100644 --- a/juniper/Makefile.toml +++ b/juniper/Makefile.toml @@ -4,13 +4,13 @@ CARGO_MAKE_CARGO_ALL_FEATURES = "" [tasks.release] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--execute", "${RELEASE_LEVEL}"] [tasks.release-dry-run] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"] [tasks.release-local-test] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "${RELEASE_LEVEL}"] [tasks.test] args = ["test", "--all-features"] diff --git a/juniper/release.toml b/juniper/release.toml index 54388c07..d3dea325 100644 --- a/juniper/release.toml +++ b/juniper/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" diff --git a/juniper_codegen/Makefile.toml b/juniper_codegen/Makefile.toml index 6eca6486..58aa74fb 100644 --- a/juniper_codegen/Makefile.toml +++ b/juniper_codegen/Makefile.toml @@ -2,10 +2,10 @@ # release config. [tasks.release] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--execute", "${RELEASE_LEVEL}"] [tasks.release-dry-run] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"] [tasks.release-local-test] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "${RELEASE_LEVEL}"] diff --git a/juniper_codegen/release.toml b/juniper_codegen/release.toml index ec5368a9..33a9caec 100644 --- a/juniper_codegen/release.toml +++ b/juniper_codegen/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" diff --git a/juniper_graphql_ws/Makefile.toml b/juniper_graphql_ws/Makefile.toml index f6bd8ee1..8a804aba 100644 --- a/juniper_graphql_ws/Makefile.toml +++ b/juniper_graphql_ws/Makefile.toml @@ -2,13 +2,14 @@ # release config. [tasks.release] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--execute", "${RELEASE_LEVEL}"] [tasks.release-dry-run] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"] [tasks.release-local-test] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "${RELEASE_LEVEL}"] + [env] CARGO_MAKE_CARGO_ALL_FEATURES = "" diff --git a/juniper_graphql_ws/release.toml b/juniper_graphql_ws/release.toml index 90382749..a7356262 100644 --- a/juniper_graphql_ws/release.toml +++ b/juniper_graphql_ws/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" diff --git a/juniper_subscriptions/Makefile.toml b/juniper_subscriptions/Makefile.toml index f0c7fd40..afbd4f96 100644 --- a/juniper_subscriptions/Makefile.toml +++ b/juniper_subscriptions/Makefile.toml @@ -3,13 +3,13 @@ # release config. [tasks.release] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--execute", "${RELEASE_LEVEL}"] [tasks.release-dry-run] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--dry-run", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--no-publish", "--no-push", "--no-tag", "${RELEASE_LEVEL}"] [tasks.release-local-test] -args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "--skip-publish", "--skip-push", "--skip-tag", "${RELEASE_LEVEL}"] +args = ["release", "--config", "${CARGO_MAKE_WORKING_DIRECTORY}/release.toml", "--no-confirm", "${RELEASE_LEVEL}"] [env] CARGO_MAKE_CARGO_ALL_FEATURES = "" diff --git a/juniper_subscriptions/release.toml b/juniper_subscriptions/release.toml index f84ce2b0..4108f647 100644 --- a/juniper_subscriptions/release.toml +++ b/juniper_subscriptions/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-commit-message = "Release {{crate_name}} {{version}}" post-release-commit-message = "Bump {{crate_name}} version to {{next_version}}" tag-message = "Release {{crate_name}} {{version}}" From 1fd518e72c955ecb8a88ed26711b3483186d7dfe Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:28:15 -0800 Subject: [PATCH 04/17] Release juniper_codegen 0.15.8 --- juniper/Cargo.toml | 2 +- juniper_codegen/Cargo.toml | 2 +- juniper_codegen/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index 0501aea3..da7af096 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -32,7 +32,7 @@ scalar-naivetime = [] schema-language = ["graphql-parser-integration"] [dependencies] -juniper_codegen = { version = "0.15.7", path = "../juniper_codegen" } +juniper_codegen = { version = "0.15.8", path = "../juniper_codegen" } anyhow = { version = "1.0.32", optional = true, default-features = false } async-trait = "0.1.39" diff --git a/juniper_codegen/Cargo.toml b/juniper_codegen/Cargo.toml index 28d44c13..b7c1ebe3 100644 --- a/juniper_codegen/Cargo.toml +++ b/juniper_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_codegen" -version = "0.15.7" +version = "0.15.8" edition = "2018" authors = [ "Magnus Hallin ", diff --git a/juniper_codegen/src/lib.rs b/juniper_codegen/src/lib.rs index 38870ff2..6098030d 100644 --- a/juniper_codegen/src/lib.rs +++ b/juniper_codegen/src/lib.rs @@ -4,7 +4,7 @@ //! You should not depend on juniper_codegen directly. //! You only need the `juniper` crate. -#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.15.7")] +#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.15.8")] #![recursion_limit = "1024"] mod result; From 3025ab0a4a0e5668b91477b03ad68e13dd5ba289 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:28:49 -0800 Subject: [PATCH 05/17] Release juniper 0.15.8 --- juniper/CHANGELOG.md | 4 ++++ juniper/Cargo.toml | 2 +- juniper/src/lib.rs | 2 +- juniper_actix/Cargo.toml | 4 ++-- juniper_codegen/Cargo.toml | 2 +- juniper_graphql_ws/Cargo.toml | 2 +- juniper_hyper/Cargo.toml | 4 ++-- juniper_iron/Cargo.toml | 4 ++-- juniper_rocket/Cargo.toml | 4 ++-- juniper_subscriptions/Cargo.toml | 2 +- juniper_warp/Cargo.toml | 4 ++-- 11 files changed, 19 insertions(+), 15 deletions(-) diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md index 68ebe542..1188b6bb 100644 --- a/juniper/CHANGELOG.md +++ b/juniper/CHANGELOG.md @@ -1,5 +1,9 @@ # master +- No changes yet + +# [[0.15.8] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.8) + - Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps. # [[0.15.7] 2021-07-08](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.7) diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index da7af096..31595280 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper" -version = "0.15.7" +version = "0.15.8" authors = [ "Magnus Hallin ", "Christoph Herzog ", diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs index c4e9bd30..c6eb1fcd 100644 --- a/juniper/src/lib.rs +++ b/juniper/src/lib.rs @@ -90,7 +90,7 @@ Juniper has not reached 1.0 yet, thus some API instability should be expected. [bson]: https://crates.io/crates/bson */ -#![doc(html_root_url = "https://docs.rs/juniper/0.15.7")] +#![doc(html_root_url = "https://docs.rs/juniper/0.15.8")] #![warn(missing_docs)] // Required for using `juniper_codegen` macros inside this crate to resolve absolute `::juniper` diff --git a/juniper_actix/Cargo.toml b/juniper_actix/Cargo.toml index f425d54a..6ad41077 100644 --- a/juniper_actix/Cargo.toml +++ b/juniper_actix/Cargo.toml @@ -18,7 +18,7 @@ http = "0.2.4" actix-web = "4.0.0-beta.8" actix-web-actors = "4.0.0-beta.6" -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } juniper_graphql_ws = { version = "0.2.5", path = "../juniper_graphql_ws", optional = true } anyhow = "1.0" @@ -35,7 +35,7 @@ tokio = "1" async-stream = "0.3" actix-test = "0.1.0-beta.3" -juniper = { version = "0.15.7", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } bytes = "1.0" env_logger = "0.8" diff --git a/juniper_codegen/Cargo.toml b/juniper_codegen/Cargo.toml index b7c1ebe3..6d467753 100644 --- a/juniper_codegen/Cargo.toml +++ b/juniper_codegen/Cargo.toml @@ -26,4 +26,4 @@ syn = { version = "1.0.60", features = ["extra-traits", "full", "parsing"], defa [dev-dependencies] derive_more = "0.99.7" futures = "0.3" -juniper = { version = "0.15.7", path = "../juniper" } +juniper = { version = "0.15.8", path = "../juniper" } diff --git a/juniper_graphql_ws/Cargo.toml b/juniper_graphql_ws/Cargo.toml index 2bd3bf4e..297b9384 100644 --- a/juniper_graphql_ws/Cargo.toml +++ b/juniper_graphql_ws/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/graphql-rust/juniper" keywords = ["apollo", "graphql", "graphql-ws", "juniper"] [dependencies] -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } juniper_subscriptions = { version = "0.15.5", path = "../juniper_subscriptions" } serde = { version = "1.0.8", features = ["derive"], default-features = false } tokio = { version = "1", features = ["macros", "rt", "time"], default-features = false } diff --git a/juniper_hyper/Cargo.toml b/juniper_hyper/Cargo.toml index d0515138..c23445b4 100644 --- a/juniper_hyper/Cargo.toml +++ b/juniper_hyper/Cargo.toml @@ -10,14 +10,14 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } hyper = {version = "0.14", features = ["server", "runtime"]} serde_json = "1.0" tokio = "1" url = "2" [dev-dependencies] -juniper = { version = "0.15.7", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } pretty_env_logger = "0.4" reqwest = { version = "0.11", features = ["blocking", "rustls-tls"] } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/juniper_iron/Cargo.toml b/juniper_iron/Cargo.toml index 4e8faf71..82491f76 100644 --- a/juniper_iron/Cargo.toml +++ b/juniper_iron/Cargo.toml @@ -13,13 +13,13 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.7", path = "../juniper" } +juniper = { version = "0.15.8", path = "../juniper" } iron = ">= 0.5, < 0.7" serde_json = "1.0.2" urlencoded = ">= 0.5, < 0.7" [dev-dependencies] -juniper = { version = "0.15.7", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } iron-test = "0.6" logger = "0.4" mount = "0.4" diff --git a/juniper_rocket/Cargo.toml b/juniper_rocket/Cargo.toml index d6e387f5..b7c80dd4 100644 --- a/juniper_rocket/Cargo.toml +++ b/juniper_rocket/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } rocket = { version = "0.5.0-rc.1", default-features = false } serde_json = "1.0.2" [dev-dependencies] -juniper = { version = "0.15.7", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } diff --git a/juniper_subscriptions/Cargo.toml b/juniper_subscriptions/Cargo.toml index 3e70511c..51cb895f 100644 --- a/juniper_subscriptions/Cargo.toml +++ b/juniper_subscriptions/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } [dev-dependencies] serde_json = "1.0" diff --git a/juniper_warp/Cargo.toml b/juniper_warp/Cargo.toml index 17bf0b84..fe6d0dde 100644 --- a/juniper_warp/Cargo.toml +++ b/juniper_warp/Cargo.toml @@ -14,7 +14,7 @@ subscriptions = ["juniper_graphql_ws"] [dependencies] anyhow = "1.0" futures = "0.3.1" -juniper = { version = "0.15.7", path = "../juniper", default-features = false } +juniper = { version = "0.15.8", path = "../juniper", default-features = false } juniper_graphql_ws = { version = "0.2.5", path = "../juniper_graphql_ws", optional = true } serde = { version = "1.0.75", features = ["derive"] } serde_json = "1.0.24" @@ -24,7 +24,7 @@ warp = "0.3" [dev-dependencies] env_logger = "0.8" -juniper = { version = "0.15.7", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } log = "0.4" percent-encoding = "2.1" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } From 12feeb0cd4bf713cec268c4014f9531b3088ff08 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:46:19 -0800 Subject: [PATCH 06/17] Release juniper_hyper 0.7.2 --- juniper_hyper/CHANGELOG.md | 4 ++++ juniper_hyper/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/juniper_hyper/CHANGELOG.md b/juniper_hyper/CHANGELOG.md index bf66bb4d..5900e564 100644 --- a/juniper_hyper/CHANGELOG.md +++ b/juniper_hyper/CHANGELOG.md @@ -2,6 +2,10 @@ - Compatibility with the latest `juniper`. +# [[0.7.2] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-0.7.2) + +- Compatibility with the latest `juniper`. + # [[0.7.1] 2021-06-07](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-0.7.1) - Compatibility with the latest `juniper`. diff --git a/juniper_hyper/Cargo.toml b/juniper_hyper/Cargo.toml index c23445b4..c8b6fd75 100644 --- a/juniper_hyper/Cargo.toml +++ b/juniper_hyper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_hyper" -version = "0.7.1" +version = "0.7.2" edition = "2018" authors = ["Damir Vandic "] description = "Juniper GraphQL integration with Hyper" From b251de65fa716340bd3e5bf3c05776dcbe693868 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:47:25 -0800 Subject: [PATCH 07/17] Release juniper_iron 0.7.5 --- juniper_iron/CHANGELOG.md | 4 ++++ juniper_iron/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/juniper_iron/CHANGELOG.md b/juniper_iron/CHANGELOG.md index 54ecaca3..890b2507 100644 --- a/juniper_iron/CHANGELOG.md +++ b/juniper_iron/CHANGELOG.md @@ -2,6 +2,10 @@ - Compatibility with the latest `juniper`. +# [[0.7.5] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-0.7.5) + +- Compatibility with the latest `juniper`. + # [[0.7.4] 2021-06-07](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-0.7.4) - Compatibility with the latest `juniper`. diff --git a/juniper_iron/Cargo.toml b/juniper_iron/Cargo.toml index 82491f76..8cb88229 100644 --- a/juniper_iron/Cargo.toml +++ b/juniper_iron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_iron" -version = "0.7.4" +version = "0.7.5" edition = "2018" authors = [ "Magnus Hallin ", From a64fdc35227331e9acf96d2c288915d923d1259a Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:48:27 -0800 Subject: [PATCH 08/17] Release juniper_rocket 0.7.2 --- juniper_rocket/CHANGELOG.md | 4 ++++ juniper_rocket/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/juniper_rocket/CHANGELOG.md b/juniper_rocket/CHANGELOG.md index e9005978..60ead3b2 100644 --- a/juniper_rocket/CHANGELOG.md +++ b/juniper_rocket/CHANGELOG.md @@ -1,5 +1,9 @@ # master +- Compatibility with the latest `juniper`. + +# [[0.7.2] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_rocket-0.7.2) + - Require async rocket support (`rocket` >= 0.5-rc1). - Compatibility with the latest `juniper`. diff --git a/juniper_rocket/Cargo.toml b/juniper_rocket/Cargo.toml index b7c80dd4..09a25a23 100644 --- a/juniper_rocket/Cargo.toml +++ b/juniper_rocket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_rocket" -version = "0.7.1" +version = "0.7.2" edition = "2018" authors = [ "Magnus Hallin ", From 5fb222e66f734f61c2bb030db75953252a451e75 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:50:29 -0800 Subject: [PATCH 09/17] Release juniper_subscriptions 0.15.6 --- juniper_graphql_ws/Cargo.toml | 2 +- juniper_subscriptions/Cargo.toml | 2 +- juniper_subscriptions/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/juniper_graphql_ws/Cargo.toml b/juniper_graphql_ws/Cargo.toml index 297b9384..d45e9e42 100644 --- a/juniper_graphql_ws/Cargo.toml +++ b/juniper_graphql_ws/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["apollo", "graphql", "graphql-ws", "juniper"] [dependencies] juniper = { version = "0.15.8", path = "../juniper", default-features = false } -juniper_subscriptions = { version = "0.15.5", path = "../juniper_subscriptions" } +juniper_subscriptions = { version = "0.15.6", path = "../juniper_subscriptions" } serde = { version = "1.0.8", features = ["derive"], default-features = false } tokio = { version = "1", features = ["macros", "rt", "time"], default-features = false } diff --git a/juniper_subscriptions/Cargo.toml b/juniper_subscriptions/Cargo.toml index 51cb895f..472a5e8e 100644 --- a/juniper_subscriptions/Cargo.toml +++ b/juniper_subscriptions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_subscriptions" -version = "0.15.5" +version = "0.15.6" edition = "2018" authors = ["nWacky "] description = "Juniper SubscriptionCoordinator and SubscriptionConnection implementations" diff --git a/juniper_subscriptions/src/lib.rs b/juniper_subscriptions/src/lib.rs index ffb2e6cc..e197534a 100644 --- a/juniper_subscriptions/src/lib.rs +++ b/juniper_subscriptions/src/lib.rs @@ -9,7 +9,7 @@ #![deny(missing_docs)] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/juniper_subscriptions/0.15.5")] +#![doc(html_root_url = "https://docs.rs/juniper_subscriptions/0.15.6")] use std::{ iter::FromIterator, From bae27e8694f6442a61382b7b8345346d22401012 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:51:12 -0800 Subject: [PATCH 10/17] Release juniper_graphql_ws 0.2.6 --- juniper_actix/Cargo.toml | 2 +- juniper_graphql_ws/Cargo.toml | 2 +- juniper_warp/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/juniper_actix/Cargo.toml b/juniper_actix/Cargo.toml index 6ad41077..39f5d0bd 100644 --- a/juniper_actix/Cargo.toml +++ b/juniper_actix/Cargo.toml @@ -19,7 +19,7 @@ actix-web = "4.0.0-beta.8" actix-web-actors = "4.0.0-beta.6" juniper = { version = "0.15.8", path = "../juniper", default-features = false } -juniper_graphql_ws = { version = "0.2.5", path = "../juniper_graphql_ws", optional = true } +juniper_graphql_ws = { version = "0.2.6", path = "../juniper_graphql_ws", optional = true } anyhow = "1.0" futures = "0.3" diff --git a/juniper_graphql_ws/Cargo.toml b/juniper_graphql_ws/Cargo.toml index d45e9e42..93cf78b8 100644 --- a/juniper_graphql_ws/Cargo.toml +++ b/juniper_graphql_ws/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_graphql_ws" -version = "0.2.5" +version = "0.2.6" edition = "2018" authors = ["Christopher Brown "] license = "BSD-2-Clause" diff --git a/juniper_warp/Cargo.toml b/juniper_warp/Cargo.toml index fe6d0dde..ee5ed1e8 100644 --- a/juniper_warp/Cargo.toml +++ b/juniper_warp/Cargo.toml @@ -15,7 +15,7 @@ subscriptions = ["juniper_graphql_ws"] anyhow = "1.0" futures = "0.3.1" juniper = { version = "0.15.8", path = "../juniper", default-features = false } -juniper_graphql_ws = { version = "0.2.5", path = "../juniper_graphql_ws", optional = true } +juniper_graphql_ws = { version = "0.2.6", path = "../juniper_graphql_ws", optional = true } serde = { version = "1.0.75", features = ["derive"] } serde_json = "1.0.24" thiserror = "1.0" From ad82364c5abcd9646cfb6bc5c138c7402285f2af Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:51:58 -0800 Subject: [PATCH 11/17] Release juniper_warp 0.6.5 --- juniper_warp/CHANGELOG.md | 4 ++++ juniper_warp/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/juniper_warp/CHANGELOG.md b/juniper_warp/CHANGELOG.md index 4dbb6af9..d7954e07 100644 --- a/juniper_warp/CHANGELOG.md +++ b/juniper_warp/CHANGELOG.md @@ -2,6 +2,10 @@ - Compatibility with the latest `juniper`. +# [[0.6.5] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_warp-0.6.5) + +- Compatibility with the latest `juniper`. + # [[0.6.4] 2021-06-07](https://github.com/graphql-rust/juniper/releases/tag/juniper_warp-0.6.4) - Compatibility with the latest `juniper`. diff --git a/juniper_warp/Cargo.toml b/juniper_warp/Cargo.toml index ee5ed1e8..4fffdba5 100644 --- a/juniper_warp/Cargo.toml +++ b/juniper_warp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_warp" -version = "0.6.4" +version = "0.6.5" edition = "2018" authors = ["Tom Houlé "] description = "Juniper GraphQL integration with Warp" From 5304237d7c919e06628c259168351b8fa3c2f55a Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 26 Jan 2022 23:53:08 -0800 Subject: [PATCH 12/17] Release juniper_actix 0.3.1 --- juniper_actix/CHANGELOG.md | 4 ++++ juniper_actix/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/juniper_actix/CHANGELOG.md b/juniper_actix/CHANGELOG.md index ffe25710..1f3481c5 100644 --- a/juniper_actix/CHANGELOG.md +++ b/juniper_actix/CHANGELOG.md @@ -1,5 +1,9 @@ # master +- Compatibility with the latest `juniper`. + +# [[0.3.1] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_actix-0.3.1) + - Require `actix-web` >= `4.0.0-beta8`. - Compatibility with the latest `juniper`. diff --git a/juniper_actix/Cargo.toml b/juniper_actix/Cargo.toml index 39f5d0bd..9192646e 100644 --- a/juniper_actix/Cargo.toml +++ b/juniper_actix/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_actix" -version = "0.3.0" +version = "0.3.1" edition = "2018" authors = ["Jordao Rosario "] description = "Juniper GraphQL integration with Actix" From bb35c66448b56c2e978be9f7318deaaec9256004 Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 2 Feb 2022 18:27:08 +0200 Subject: [PATCH 13/17] Make validation execute in stages to avoid possible infinite recursion --- juniper/CHANGELOG.md | 4 + juniper/src/validation/context.rs | 4 + juniper/src/validation/mod.rs | 3 +- juniper/src/validation/rules/mod.rs | 68 +++++++++++- .../rules/overlapping_fields_can_be_merged.rs | 40 +------ juniper/src/validation/test_harness.rs | 102 ++++++++++++++---- 6 files changed, 164 insertions(+), 57 deletions(-) diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md index 1188b6bb..7d10f41e 100644 --- a/juniper/CHANGELOG.md +++ b/juniper/CHANGELOG.md @@ -2,6 +2,10 @@ - No changes yet +# [[0.15.9] 2022-02-02](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.9) + +- Fix infinite recursion on malformed queries with nested recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps. + # [[0.15.8] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.8) - Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps. diff --git a/juniper/src/validation/context.rs b/juniper/src/validation/context.rs index 9a02ae15..d90e7362 100644 --- a/juniper/src/validation/context.rs +++ b/juniper/src/validation/context.rs @@ -97,6 +97,10 @@ impl<'a, S: Debug> ValidatorContext<'a, S> { self.errors.push(RuleError::new(message, locations)) } + pub(crate) fn has_errors(&self) -> bool { + !self.errors.is_empty() + } + #[doc(hidden)] pub fn into_errors(mut self) -> Vec { self.errors.sort(); diff --git a/juniper/src/validation/mod.rs b/juniper/src/validation/mod.rs index 4a543528..c2759ec9 100644 --- a/juniper/src/validation/mod.rs +++ b/juniper/src/validation/mod.rs @@ -21,6 +21,7 @@ pub use self::{ #[cfg(test)] pub use self::test_harness::{ - expect_fails_rule, expect_fails_rule_with_schema, expect_passes_rule, + expect_fails_fn, expect_fails_fn_with_schema, expect_fails_rule, expect_fails_rule_with_schema, + expect_passes_fn, expect_passes_fn_with_schema, expect_passes_rule, expect_passes_rule_with_schema, }; diff --git a/juniper/src/validation/rules/mod.rs b/juniper/src/validation/rules/mod.rs index 211c1726..60a38d13 100644 --- a/juniper/src/validation/rules/mod.rs +++ b/juniper/src/validation/rules/mod.rs @@ -35,7 +35,14 @@ pub fn visit_all_rules<'a, S: Debug>(ctx: &mut ValidatorContext<'a, S>, doc: &'a where S: ScalarValue, { - let mut mv = MultiVisitorNil + // Some validators are depending on the results of other ones. + // For example, validators checking fragments usually rely on the fact that + // they have no cycles (`no_fragment_cycles`), otherwise may stall in an + // infinite recursion. So, we should run validators in stages, moving to the + // next stage only once the previous succeeds. This is better than making + // every single validator being aware of fragments cycles and/or other + // assumptions. + let mut stage1 = MultiVisitorNil .with(self::arguments_of_correct_type::factory()) .with(self::default_values_of_correct_type::factory()) .with(self::fields_on_correct_type::factory()) @@ -49,7 +56,6 @@ where .with(self::no_undefined_variables::factory()) .with(self::no_unused_fragments::factory()) .with(self::no_unused_variables::factory()) - .with(self::overlapping_fields_can_be_merged::factory()) .with(self::possible_fragment_spreads::factory()) .with(self::provided_non_null_arguments::factory()) .with(self::scalar_leafs::factory()) @@ -60,6 +66,62 @@ where .with(self::unique_variable_names::factory()) .with(self::variables_are_input_types::factory()) .with(self::variables_in_allowed_position::factory()); + visit(&mut stage1, ctx, doc); + if ctx.has_errors() { + return; + } - visit(&mut mv, ctx, doc) + let mut stage2 = MultiVisitorNil.with(self::overlapping_fields_can_be_merged::factory()); + visit(&mut stage2, ctx, doc); +} + +#[cfg(test)] +mod tests { + use crate::{parser::SourcePosition, DefaultScalarValue}; + + use crate::validation::{expect_fails_fn, RuleError}; + + #[test] + fn handles_recursive_fragments() { + expect_fails_fn::<_, DefaultScalarValue>( + super::visit_all_rules, + "fragment f on QueryRoot { ...f }", + &[ + RuleError::new( + "Fragment \"f\" is never used", + &[SourcePosition::new(0, 0, 0)], + ), + RuleError::new( + "Cannot spread fragment \"f\"", + &[SourcePosition::new(26, 0, 26)], + ), + ], + ); + } + + #[test] + fn handles_nested_recursive_fragments() { + expect_fails_fn::<_, DefaultScalarValue>( + super::visit_all_rules, + "fragment f on QueryRoot { a { ...f a { ...f } } }", + &[ + RuleError::new( + "Fragment \"f\" is never used", + &[SourcePosition::new(0, 0, 0)], + ), + RuleError::new( + r#"Unknown field "a" on type "QueryRoot""#, + &[SourcePosition::new(26, 0, 26)], + ), + RuleError::new( + "Cannot spread fragment \"f\"", + &[SourcePosition::new(30, 0, 30)], + ), + RuleError::new( + "Cannot spread fragment \"f\"", + &[SourcePosition::new(39, 0, 39)], + ), + ], + ); + } } diff --git a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs index f26dcfdf..30ec9226 100644 --- a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -33,6 +33,7 @@ struct PairSet<'a> { data: HashMap<&'a str, HashMap<&'a str, bool>>, } +#[derive(Debug)] struct OrderedMap { data: HashMap, insert_order: Vec, @@ -172,13 +173,6 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { ); for frag_name2 in &fragment_names[i + 1..] { - // Prevent infinite fragment recursion. This case is - // caught by fragment validators, but because the validation is - // done in parallel we can't rely on fragments being - // non-recursive here. - if frag_name1 == frag_name2 { - continue; - } self.collect_conflicts_between_fragments( &mut conflicts, frag_name1, @@ -202,10 +196,8 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { ) where S: ScalarValue, { - // Prevent infinite fragment recursion. This case is - // caught by fragment validators, but because the validation is - // done in parallel we can't rely on fragments being - // non-recursive here. + // Early return on fragment recursion, as it makes no sense. + // Fragment recursions are prevented by `no_fragment_cycles` validator. if fragment_name1 == fragment_name2 { return; } @@ -293,10 +285,8 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> { self.collect_conflicts_between(conflicts, mutually_exclusive, field_map, &field_map2, ctx); for fragment_name2 in fragment_names2 { - // Prevent infinite fragment recursion. This case is - // caught by fragment validators, but because the validation is - // done in parallel we can't rely on fragments being - // non-recursive here. + // Early return on fragment recursion, as it makes no sense. + // Fragment recursions are prevented by `no_fragment_cycles` validator. if fragment_name == fragment_name2 { return; } @@ -2279,26 +2269,6 @@ mod tests { ); } - #[test] - fn handles_recursive_fragments() { - expect_passes_rule_with_schema::< - _, - EmptyMutation<()>, - EmptySubscription<()>, - _, - _, - DefaultScalarValue, - >( - QueryRoot, - EmptyMutation::new(), - EmptySubscription::new(), - factory, - r#" - fragment f on Query { ...f } - "#, - ); - } - #[test] fn error_message_contains_hint_for_alias_conflict() { assert_eq!( diff --git a/juniper/src/validation/test_harness.rs b/juniper/src/validation/test_harness.rs index a2af2194..a7ff1429 100644 --- a/juniper/src/validation/test_harness.rs +++ b/juniper/src/validation/test_harness.rs @@ -1,5 +1,5 @@ use crate::{ - ast::{FromInputValue, InputValue}, + ast::{Document, FromInputValue, InputValue}, executor::Registry, parser::parse_document_source, schema::{ @@ -812,20 +812,13 @@ where } } -pub fn validate<'a, Q, M, Sub, V, F, S>( - r: Q, - m: M, - s: Sub, - q: &'a str, - factory: F, -) -> Vec +pub fn validate<'a, Q, M, Sub, F, S>(r: Q, m: M, s: Sub, q: &'a str, visit_fn: F) -> Vec where S: ScalarValue + 'a, Q: GraphQLType, M: GraphQLType, Sub: GraphQLType, - V: Visitor<'a, S> + 'a, - F: Fn() -> V, + F: FnOnce(&mut ValidatorContext<'a, S>, &'a Document), { let mut root = RootNode::new_with_scalar_value(r, m, s); @@ -864,10 +857,7 @@ where parse_document_source(q, &root.schema).expect(&format!("Parse error on input {:#?}", q)); let mut ctx = ValidatorContext::new(unsafe { ::std::mem::transmute(&root.schema) }, &doc); - let mut mv = MultiVisitorNil.with(factory()); - visit(&mut mv, &mut ctx, unsafe { - ::std::mem::transmute(doc.as_slice()) - }); + visit_fn(&mut ctx, unsafe { ::std::mem::transmute(doc.as_slice()) }); ctx.into_errors() } @@ -881,6 +871,14 @@ where expect_passes_rule_with_schema(QueryRoot, MutationRoot, SubscriptionRoot, factory, q); } +pub fn expect_passes_fn<'a, F, S>(visit_fn: F, q: &'a str) +where + S: ScalarValue + 'a, + F: FnOnce(&mut ValidatorContext<'a, S>, &'a Document), +{ + expect_passes_fn_with_schema(QueryRoot, MutationRoot, SubscriptionRoot, visit_fn, q); +} + pub fn expect_passes_rule_with_schema<'a, Q, M, Sub, V, F, S>( r: Q, m: M, @@ -893,9 +891,12 @@ pub fn expect_passes_rule_with_schema<'a, Q, M, Sub, V, F, S>( M: GraphQLType, Sub: GraphQLType, V: Visitor<'a, S> + 'a, - F: Fn() -> V, + F: FnOnce() -> V, { - let errs = validate(r, m, s, q, factory); + let errs = validate(r, m, s, q, move |ctx, doc| { + let mut mv = MultiVisitorNil.with(factory()); + visit(&mut mv, ctx, unsafe { ::std::mem::transmute(doc) }); + }); if !errs.is_empty() { print_errors(&errs); @@ -903,6 +904,27 @@ pub fn expect_passes_rule_with_schema<'a, Q, M, Sub, V, F, S>( } } +pub fn expect_passes_fn_with_schema<'a, Q, M, Sub, F, S>( + r: Q, + m: M, + s: Sub, + visit_fn: F, + q: &'a str, +) where + S: ScalarValue + 'a, + Q: GraphQLType, + M: GraphQLType, + Sub: GraphQLType, + F: FnOnce(&mut ValidatorContext<'a, S>, &'a Document), +{ + let errs = validate(r, m, s, q, visit_fn); + + if !errs.is_empty() { + print_errors(&errs); + panic!("Expected `visit_fn` to pass, but errors found"); + } +} + pub fn expect_fails_rule<'a, V, F, S>(factory: F, q: &'a str, expected_errors: &[RuleError]) where S: ScalarValue + 'a, @@ -912,6 +934,14 @@ where expect_fails_rule_with_schema(QueryRoot, MutationRoot, factory, q, expected_errors); } +pub fn expect_fails_fn<'a, F, S>(visit_fn: F, q: &'a str, expected_errors: &[RuleError]) +where + S: ScalarValue + 'a, + F: FnOnce(&mut ValidatorContext<'a, S>, &'a Document), +{ + expect_fails_fn_with_schema(QueryRoot, MutationRoot, visit_fn, q, expected_errors); +} + pub fn expect_fails_rule_with_schema<'a, Q, M, V, F, S>( r: Q, m: M, @@ -923,9 +953,18 @@ pub fn expect_fails_rule_with_schema<'a, Q, M, V, F, S>( Q: GraphQLType, M: GraphQLType, V: Visitor<'a, S> + 'a, - F: Fn() -> V, + F: FnOnce() -> V, { - let errs = validate(r, m, crate::EmptySubscription::::new(), q, factory); + let errs = validate( + r, + m, + crate::EmptySubscription::::new(), + q, + move |ctx, doc| { + let mut mv = MultiVisitorNil.with(factory()); + visit(&mut mv, ctx, unsafe { ::std::mem::transmute(doc) }); + }, + ); if errs.is_empty() { panic!("Expected rule to fail, but no errors were found"); @@ -940,6 +979,33 @@ pub fn expect_fails_rule_with_schema<'a, Q, M, V, F, S>( } } +pub fn expect_fails_fn_with_schema<'a, Q, M, F, S>( + r: Q, + m: M, + visit_fn: F, + q: &'a str, + expected_errors: &[RuleError], +) where + S: ScalarValue + 'a, + Q: GraphQLType, + M: GraphQLType, + F: FnOnce(&mut ValidatorContext<'a, S>, &'a Document), +{ + let errs = validate(r, m, crate::EmptySubscription::::new(), q, visit_fn); + + if errs.is_empty() { + panic!("Expected `visit_fn`` to fail, but no errors were found"); + } else if errs != expected_errors { + println!("==> Expected errors:"); + print_errors(expected_errors); + + println!("\n==> Actual errors:"); + print_errors(&errs); + + panic!("Unexpected set of errors found"); + } +} + fn print_errors(errs: &[RuleError]) { for err in errs { for p in err.locations() { From a0a566bc5bdbb50078df30148b028e15ffcfc261 Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 2 Feb 2022 18:28:30 +0200 Subject: [PATCH 14/17] Release `juniper_codegen` 0.15.9 --- juniper/Cargo.toml | 2 +- juniper_codegen/Cargo.toml | 2 +- juniper_codegen/src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index 31595280..50f34cef 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -32,7 +32,7 @@ scalar-naivetime = [] schema-language = ["graphql-parser-integration"] [dependencies] -juniper_codegen = { version = "0.15.8", path = "../juniper_codegen" } +juniper_codegen = { version = "0.15.9", path = "../juniper_codegen" } anyhow = { version = "1.0.32", optional = true, default-features = false } async-trait = "0.1.39" diff --git a/juniper_codegen/Cargo.toml b/juniper_codegen/Cargo.toml index 6d467753..80717300 100644 --- a/juniper_codegen/Cargo.toml +++ b/juniper_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_codegen" -version = "0.15.8" +version = "0.15.9" edition = "2018" authors = [ "Magnus Hallin ", diff --git a/juniper_codegen/src/lib.rs b/juniper_codegen/src/lib.rs index 6098030d..aaa04c98 100644 --- a/juniper_codegen/src/lib.rs +++ b/juniper_codegen/src/lib.rs @@ -4,7 +4,7 @@ //! You should not depend on juniper_codegen directly. //! You only need the `juniper` crate. -#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.15.8")] +#![doc(html_root_url = "https://docs.rs/juniper_codegen/0.15.9")] #![recursion_limit = "1024"] mod result; @@ -495,7 +495,7 @@ pub fn graphql_object(args: TokenStream, input: TokenStream) -> TokenStream { /// struct UserID(String); /// /// #[juniper::graphql_scalar( -/// // You can rename the type for GraphQL by specifying the name here. +/// // You can rename the type for GraphQL by specifying the name here. /// name = "MyName", /// // You can also specify a description here. /// // If present, doc comments will be ignored. From 855137cde6e080bf29c22e0a646b3ae900fb94ed Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 2 Feb 2022 18:33:41 +0200 Subject: [PATCH 15/17] Release `juniper` 0.15.9 --- juniper/Cargo.toml | 2 +- juniper/src/lib.rs | 2 +- juniper_actix/Cargo.toml | 4 ++-- juniper_codegen/Cargo.toml | 2 +- juniper_graphql_ws/Cargo.toml | 2 +- juniper_hyper/Cargo.toml | 4 ++-- juniper_iron/Cargo.toml | 4 ++-- juniper_rocket/Cargo.toml | 4 ++-- juniper_subscriptions/Cargo.toml | 2 +- juniper_warp/Cargo.toml | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index 50f34cef..3b083370 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper" -version = "0.15.8" +version = "0.15.9" authors = [ "Magnus Hallin ", "Christoph Herzog ", diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs index c6eb1fcd..85b0bafb 100644 --- a/juniper/src/lib.rs +++ b/juniper/src/lib.rs @@ -90,7 +90,7 @@ Juniper has not reached 1.0 yet, thus some API instability should be expected. [bson]: https://crates.io/crates/bson */ -#![doc(html_root_url = "https://docs.rs/juniper/0.15.8")] +#![doc(html_root_url = "https://docs.rs/juniper/0.15.9")] #![warn(missing_docs)] // Required for using `juniper_codegen` macros inside this crate to resolve absolute `::juniper` diff --git a/juniper_actix/Cargo.toml b/juniper_actix/Cargo.toml index 9192646e..c59e0dfa 100644 --- a/juniper_actix/Cargo.toml +++ b/juniper_actix/Cargo.toml @@ -18,7 +18,7 @@ http = "0.2.4" actix-web = "4.0.0-beta.8" actix-web-actors = "4.0.0-beta.6" -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } juniper_graphql_ws = { version = "0.2.6", path = "../juniper_graphql_ws", optional = true } anyhow = "1.0" @@ -35,7 +35,7 @@ tokio = "1" async-stream = "0.3" actix-test = "0.1.0-beta.3" -juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.9", path = "../juniper", features = ["expose-test-schema"] } bytes = "1.0" env_logger = "0.8" diff --git a/juniper_codegen/Cargo.toml b/juniper_codegen/Cargo.toml index 80717300..dfe54e63 100644 --- a/juniper_codegen/Cargo.toml +++ b/juniper_codegen/Cargo.toml @@ -26,4 +26,4 @@ syn = { version = "1.0.60", features = ["extra-traits", "full", "parsing"], defa [dev-dependencies] derive_more = "0.99.7" futures = "0.3" -juniper = { version = "0.15.8", path = "../juniper" } +juniper = { version = "0.15.9", path = "../juniper" } diff --git a/juniper_graphql_ws/Cargo.toml b/juniper_graphql_ws/Cargo.toml index 93cf78b8..e7f1ce34 100644 --- a/juniper_graphql_ws/Cargo.toml +++ b/juniper_graphql_ws/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/graphql-rust/juniper" keywords = ["apollo", "graphql", "graphql-ws", "juniper"] [dependencies] -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } juniper_subscriptions = { version = "0.15.6", path = "../juniper_subscriptions" } serde = { version = "1.0.8", features = ["derive"], default-features = false } tokio = { version = "1", features = ["macros", "rt", "time"], default-features = false } diff --git a/juniper_hyper/Cargo.toml b/juniper_hyper/Cargo.toml index c8b6fd75..d33767d1 100644 --- a/juniper_hyper/Cargo.toml +++ b/juniper_hyper/Cargo.toml @@ -10,14 +10,14 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } hyper = {version = "0.14", features = ["server", "runtime"]} serde_json = "1.0" tokio = "1" url = "2" [dev-dependencies] -juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.9", path = "../juniper", features = ["expose-test-schema"] } pretty_env_logger = "0.4" reqwest = { version = "0.11", features = ["blocking", "rustls-tls"] } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/juniper_iron/Cargo.toml b/juniper_iron/Cargo.toml index 8cb88229..29d95d85 100644 --- a/juniper_iron/Cargo.toml +++ b/juniper_iron/Cargo.toml @@ -13,13 +13,13 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.8", path = "../juniper" } +juniper = { version = "0.15.9", path = "../juniper" } iron = ">= 0.5, < 0.7" serde_json = "1.0.2" urlencoded = ">= 0.5, < 0.7" [dev-dependencies] -juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.9", path = "../juniper", features = ["expose-test-schema"] } iron-test = "0.6" logger = "0.4" mount = "0.4" diff --git a/juniper_rocket/Cargo.toml b/juniper_rocket/Cargo.toml index 09a25a23..7b68c0a2 100644 --- a/juniper_rocket/Cargo.toml +++ b/juniper_rocket/Cargo.toml @@ -13,9 +13,9 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } rocket = { version = "0.5.0-rc.1", default-features = false } serde_json = "1.0.2" [dev-dependencies] -juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.9", path = "../juniper", features = ["expose-test-schema"] } diff --git a/juniper_subscriptions/Cargo.toml b/juniper_subscriptions/Cargo.toml index 472a5e8e..d7bb9781 100644 --- a/juniper_subscriptions/Cargo.toml +++ b/juniper_subscriptions/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/graphql-rust/juniper" [dependencies] futures = "0.3.1" -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } [dev-dependencies] serde_json = "1.0" diff --git a/juniper_warp/Cargo.toml b/juniper_warp/Cargo.toml index 4fffdba5..11c10449 100644 --- a/juniper_warp/Cargo.toml +++ b/juniper_warp/Cargo.toml @@ -14,7 +14,7 @@ subscriptions = ["juniper_graphql_ws"] [dependencies] anyhow = "1.0" futures = "0.3.1" -juniper = { version = "0.15.8", path = "../juniper", default-features = false } +juniper = { version = "0.15.9", path = "../juniper", default-features = false } juniper_graphql_ws = { version = "0.2.6", path = "../juniper_graphql_ws", optional = true } serde = { version = "1.0.75", features = ["derive"] } serde_json = "1.0.24" @@ -24,7 +24,7 @@ warp = "0.3" [dev-dependencies] env_logger = "0.8" -juniper = { version = "0.15.8", path = "../juniper", features = ["expose-test-schema"] } +juniper = { version = "0.15.9", path = "../juniper", features = ["expose-test-schema"] } log = "0.4" percent-encoding = "2.1" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } From 6dbb5741c7f0d13e7e990e32addaa81e1f0f398e Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 2 Feb 2022 18:36:00 +0200 Subject: [PATCH 16/17] Release `juniper_hyper` 0.7.3 --- juniper_hyper/CHANGELOG.md | 6 +++++- juniper_hyper/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/juniper_hyper/CHANGELOG.md b/juniper_hyper/CHANGELOG.md index 5900e564..9b44d76c 100644 --- a/juniper_hyper/CHANGELOG.md +++ b/juniper_hyper/CHANGELOG.md @@ -2,7 +2,11 @@ - Compatibility with the latest `juniper`. -# [[0.7.2] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-0.7.2) +# [[0.7.3] 2022-02-02](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-v0.7.3) + +- Compatibility with the latest `juniper`. + +# [[0.7.2] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_hyper-v0.7.2) - Compatibility with the latest `juniper`. diff --git a/juniper_hyper/Cargo.toml b/juniper_hyper/Cargo.toml index d33767d1..6b0cffa4 100644 --- a/juniper_hyper/Cargo.toml +++ b/juniper_hyper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_hyper" -version = "0.7.2" +version = "0.7.3" edition = "2018" authors = ["Damir Vandic "] description = "Juniper GraphQL integration with Hyper" From 82761736ceedeeff2f1faa021d637ba43706a43a Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 2 Feb 2022 18:37:23 +0200 Subject: [PATCH 17/17] Release `juniper_iron` 0.7.6 --- juniper_iron/CHANGELOG.md | 6 +++++- juniper_iron/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/juniper_iron/CHANGELOG.md b/juniper_iron/CHANGELOG.md index 890b2507..3938f03e 100644 --- a/juniper_iron/CHANGELOG.md +++ b/juniper_iron/CHANGELOG.md @@ -2,7 +2,11 @@ - Compatibility with the latest `juniper`. -# [[0.7.5] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-0.7.5) +# [[0.7.6] 2022-02-02](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-v0.7.6) + +- Compatibility with the latest `juniper`. + +# [[0.7.5] 2022-01-26](https://github.com/graphql-rust/juniper/releases/tag/juniper_iron-v0.7.5) - Compatibility with the latest `juniper`. diff --git a/juniper_iron/Cargo.toml b/juniper_iron/Cargo.toml index 29d95d85..46239046 100644 --- a/juniper_iron/Cargo.toml +++ b/juniper_iron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "juniper_iron" -version = "0.7.5" +version = "0.7.6" edition = "2018" authors = [ "Magnus Hallin ",